feat: Add support for EKS Auto Mode and EKS Hybrid nodes (#3225)

* feat: Add support for EKS hybrid nodes

* feat: Add support for EKS Auto Mode

* chore: Update test directory names

* chore: Clean up examples and tests

* fix: Clean up and last minute changes for GA

* chore: Formatting

* chore: Bump min required version for new features

* fix: Corrects from test/validation on existing clusters

* feat: Add policy for custom tags on EKS Auto Mode, validate examples

* chore: Expand on `CAM` acronym

* chore: Update README to match examples
This commit is contained in:
Bryant Biggs
2024-12-04 09:24:21 -06:00
committed by GitHub
parent 6866b40bec
commit 3b974d33ad
62 changed files with 3896 additions and 441 deletions

227
README.md
View File

@@ -25,6 +25,124 @@ Please note that we strive to provide a comprehensive suite of documentation for
## Usage
### EKS Auto Mode
```hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.31"
cluster_name = "example"
cluster_version = "1.31"
# Optional
cluster_endpoint_public_access = true
# Optional: Adds the current caller identity as an administrator via cluster access entry
enable_cluster_creator_admin_permissions = true
cluster_compute_config = {
enabled = true
node_pools = ["general-purpose"]
}
vpc_id = "vpc-1234556abcdef"
subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"]
tags = {
Environment = "dev"
Terraform = "true"
}
}
```
### EKS Hybrid Nodes
```hcl
locals {
# RFC 1918 IP ranges supported
remote_network_cidr = "172.16.0.0/16"
remote_node_cidr = cidrsubnet(local.remote_network_cidr, 2, 0)
remote_pod_cidr = cidrsubnet(local.remote_network_cidr, 2, 1)
}
# SSM and IAM Roles Anywhere supported - SSM is default
module "eks_hybrid_node_role" {
source = "terraform-aws-modules/eks/aws//modules/hybrid-node-role"
version = "~> 20.31"
tags = {
Environment = "dev"
Terraform = "true"
}
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.31"
cluster_name = "example"
cluster_version = "1.31"
cluster_addons = {
coredns = {}
eks-pod-identity-agent = {}
kube-proxy = {}
}
# Optional
cluster_endpoint_public_access = true
# Optional: Adds the current caller identity as an administrator via cluster access entry
enable_cluster_creator_admin_permissions = true
create_node_security_group = false
cluster_security_group_additional_rules = {
hybrid-all = {
cidr_blocks = [local.remote_network_cidr]
description = "Allow all traffic from remote node/pod network"
from_port = 0
to_port = 0
protocol = "all"
type = "ingress"
}
}
# Optional
cluster_compute_config = {
enabled = true
node_pools = ["system"]
}
access_entries = {
hybrid-node-role = {
principal_arn = module.eks_hybrid_node_role.arn
type = "HYBRID_LINUX"
}
}
vpc_id = "vpc-1234556abcdef"
subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"]
cluster_remote_network_config = {
remote_node_networks = {
cidrs = [local.remote_node_cidr]
}
# Required if running webhooks on Hybrid nodes
remote_pod_networks = {
cidrs = [local.remote_pod_cidr]
}
}
tags = {
Environment = "dev"
Terraform = "true"
}
}
```
### EKS Managed Node Group
```hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
@@ -33,8 +151,7 @@ module "eks" {
cluster_name = "my-cluster"
cluster_version = "1.31"
cluster_endpoint_public_access = true
bootstrap_self_managed_addons = false
cluster_addons = {
coredns = {}
eks-pod-identity-agent = {}
@@ -42,6 +159,12 @@ module "eks" {
vpc-cni = {}
}
# Optional
cluster_endpoint_public_access = true
# Optional: Adds the current caller identity as an administrator via cluster access entry
enable_cluster_creator_admin_permissions = true
vpc_id = "vpc-1234556abcdef"
subnet_ids = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"]
control_plane_subnet_ids = ["subnet-xyzde987", "subnet-slkjf456", "subnet-qeiru789"]
@@ -63,14 +186,30 @@ module "eks" {
}
}
# Cluster access entry
# To add the current caller identity as an administrator
enable_cluster_creator_admin_permissions = true
tags = {
Environment = "dev"
Terraform = "true"
}
}
```
### Cluster Access Entry
When enabling `authentication_mode = "API_AND_CONFIG_MAP"`, EKS will automatically create an access entry for the IAM role(s) used by managed node group(s) and Fargate profile(s). There are no additional actions required by users. For self-managed node groups and the Karpenter sub-module, this project automatically adds the access entry on behalf of users so there are no additional actions required by users.
On clusters that were created prior to cluster access management (CAM) support, there will be an existing access entry for the cluster creator. This was previously not visible when using `aws-auth` ConfigMap, but will become visible when access entry is enabled.
```hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
# Truncated for brevity ...
access_entries = {
# One access entry with a policy associated
example = {
principal_arn = "arn:aws:iam::123456789012:role/something"
principal_arn = "arn:aws:iam::123456789012:role/something"
policy_associations = {
example = {
@@ -83,20 +222,9 @@ module "eks" {
}
}
}
tags = {
Environment = "dev"
Terraform = "true"
}
}
```
### Cluster Access Entry
When enabling `authentication_mode = "API_AND_CONFIG_MAP"`, EKS will automatically create an access entry for the IAM role(s) used by managed node group(s) and Fargate profile(s). There are no additional actions required by users. For self-managed node groups and the Karpenter sub-module, this project automatically adds the access entry on behalf of users so there are no additional actions required by users.
On clusters that were created prior to CAM support, there will be an existing access entry for the cluster creator. This was previously not visible when using `aws-auth` ConfigMap, but will become visible when access entry is enabled.
### Bootstrap Cluster Creator Admin Permissions
Setting the `bootstrap_cluster_creator_admin_permissions` is a one time operation when the cluster is created; it cannot be modified later through the EKS API. In this project we are hardcoding this to `false`. If users wish to achieve the same functionality, we will do that through an access entry which can be enabled or disabled at any time of their choosing using the variable `enable_cluster_creator_admin_permissions`
@@ -133,17 +261,31 @@ module "eks" {
eks_managed_node_groups = {
example = {
# The EKS AL2023 NVIDIA AMI provides all of the necessary components
# for accelerated workloads w/ EFA
ami_type = "AL2023_x86_64_NVIDIA"
instance_types = ["p5.48xlarge"]
# Exposes all EFA interfaces on the launch template created by the node group(s)
# This would expose all 32 EFA interfaces for the p5.48xlarge instance type
enable_efa_support = true
pre_bootstrap_user_data = <<-EOT
# Mount NVME instance store volumes since they are typically
# available on instance types that support EFA
setup-local-disks raid0
EOT
# Mount instance store volumes in RAID-0 for kubelet and containerd
# https://github.com/awslabs/amazon-eks-ami/blob/master/doc/USER_GUIDE.md#raid-0-for-kubelet-and-containerd-raid0
cloudinit_pre_nodeadm = [
{
content_type = "application/node.eks.aws"
content = <<-EOT
---
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
instance:
localStorage:
strategy: RAID0
EOT
}
]
# EFA should only be enabled when connecting 2 or more nodes
# Do not use EFA on a single node workload
@@ -157,9 +299,11 @@ module "eks" {
## Examples
- [EKS Managed Node Group](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples/eks-managed-node-group): EKS Cluster using EKS managed node groups
- [EKS Auto Mode](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples/eks-auto-mode): EKS Cluster with EKS Auto Mode
- [EKS Hybrid Nodes](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples/eks-hybrid-nodes): EKS Cluster with EKS Hybrid nodes
- [EKS Managed Node Group](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples/eks-managed-node-group): EKS Cluster with EKS managed node group(s)
- [Karpenter](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples/karpenter): EKS Cluster with [Karpenter](https://karpenter.sh/) provisioned for intelligent data plane management
- [Self Managed Node Group](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples/self-managed-node-group): EKS Cluster using self-managed node groups
- [Self Managed Node Group](https://github.com/terraform-aws-modules/terraform-aws-eks/tree/master/examples/self-managed-node-group): EKS Cluster with self-managed node group(s)
## Contributing
@@ -174,7 +318,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
| <a name="requirement_time"></a> [time](#requirement\_time) | >= 0.9 |
| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 3.0 |
@@ -182,7 +326,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
| <a name="provider_time"></a> [time](#provider\_time) | >= 0.9 |
| <a name="provider_tls"></a> [tls](#provider\_tls) | >= 3.0 |
@@ -210,9 +354,14 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| [aws_iam_openid_connect_provider.oidc_provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_openid_connect_provider) | resource |
| [aws_iam_policy.cluster_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.cni_ipv6_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.eks_auto_custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_role.eks_auto](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_attachment.additional](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.cluster_encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.eks_auto](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.eks_auto_additional](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.eks_auto_custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_security_group.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group.node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
@@ -223,6 +372,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| [aws_eks_addon_version.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_addon_version) | data source |
| [aws_iam_policy_document.assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.cni_ipv6_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.eks_auto_custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.node_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_session_context.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_session_context) | data source |
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
| [tls_certificate.this](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/data-sources/certificate) | data source |
@@ -242,6 +393,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| <a name="input_cluster_additional_security_group_ids"></a> [cluster\_additional\_security\_group\_ids](#input\_cluster\_additional\_security\_group\_ids) | List of additional, externally created security group IDs to attach to the cluster control plane | `list(string)` | `[]` | no |
| <a name="input_cluster_addons"></a> [cluster\_addons](#input\_cluster\_addons) | Map of cluster addon configurations to enable for the cluster. Addon name can be the map keys or set with `name` | `any` | `{}` | no |
| <a name="input_cluster_addons_timeouts"></a> [cluster\_addons\_timeouts](#input\_cluster\_addons\_timeouts) | Create, update, and delete timeout configurations for the cluster addons | `map(string)` | `{}` | no |
| <a name="input_cluster_compute_config"></a> [cluster\_compute\_config](#input\_cluster\_compute\_config) | Configuration block for the cluster compute configuration | `any` | `{}` | no |
| <a name="input_cluster_enabled_log_types"></a> [cluster\_enabled\_log\_types](#input\_cluster\_enabled\_log\_types) | A list of the desired control plane logs to enable. For more information, see Amazon EKS Control Plane Logging documentation (https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html) | `list(string)` | <pre>[<br/> "audit",<br/> "api",<br/> "authenticator"<br/>]</pre> | no |
| <a name="input_cluster_encryption_config"></a> [cluster\_encryption\_config](#input\_cluster\_encryption\_config) | Configuration block with encryption configuration for the cluster. To disable secret encryption, set this value to `{}` | `any` | <pre>{<br/> "resources": [<br/> "secrets"<br/> ]<br/>}</pre> | no |
| <a name="input_cluster_encryption_policy_description"></a> [cluster\_encryption\_policy\_description](#input\_cluster\_encryption\_policy\_description) | Description of the cluster encryption policy created | `string` | `"Cluster encryption policy to allow cluster role to utilize CMK provided"` | no |
@@ -255,6 +407,7 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| <a name="input_cluster_identity_providers"></a> [cluster\_identity\_providers](#input\_cluster\_identity\_providers) | Map of cluster identity provider configurations to enable for the cluster. Note - this is different/separate from IRSA | `any` | `{}` | no |
| <a name="input_cluster_ip_family"></a> [cluster\_ip\_family](#input\_cluster\_ip\_family) | The IP family used to assign Kubernetes pod and service addresses. Valid values are `ipv4` (default) and `ipv6`. You can only specify an IP family when you create a cluster, changing this value will force a new cluster to be created | `string` | `"ipv4"` | no |
| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `""` | no |
| <a name="input_cluster_remote_network_config"></a> [cluster\_remote\_network\_config](#input\_cluster\_remote\_network\_config) | Configuration block for the cluster remote network configuration | `any` | `{}` | no |
| <a name="input_cluster_security_group_additional_rules"></a> [cluster\_security\_group\_additional\_rules](#input\_cluster\_security\_group\_additional\_rules) | List of additional security group rules to add to the cluster security group created. Set `source_node_security_group = true` inside rules to set the `node_security_group` as source | `any` | `{}` | no |
| <a name="input_cluster_security_group_description"></a> [cluster\_security\_group\_description](#input\_cluster\_security\_group\_description) | Description of the cluster security group created | `string` | `"EKS cluster security group"` | no |
| <a name="input_cluster_security_group_id"></a> [cluster\_security\_group\_id](#input\_cluster\_security\_group\_id) | Existing security group ID to be attached to the cluster | `string` | `""` | no |
@@ -274,8 +427,9 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| <a name="input_create_cluster_primary_security_group_tags"></a> [create\_cluster\_primary\_security\_group\_tags](#input\_create\_cluster\_primary\_security\_group\_tags) | Indicates whether or not to tag the cluster's primary security group. This security group is created by the EKS service, not the module, and therefore tagging is handled after cluster creation | `bool` | `true` | no |
| <a name="input_create_cluster_security_group"></a> [create\_cluster\_security\_group](#input\_create\_cluster\_security\_group) | Determines if a security group is created for the cluster. Note: the EKS service creates a primary security group for the cluster by default | `bool` | `true` | no |
| <a name="input_create_cni_ipv6_iam_policy"></a> [create\_cni\_ipv6\_iam\_policy](#input\_create\_cni\_ipv6\_iam\_policy) | Determines whether to create an [`AmazonEKS_CNI_IPv6_Policy`](https://docs.aws.amazon.com/eks/latest/userguide/cni-iam-role.html#cni-iam-role-create-ipv6-policy) | `bool` | `false` | no |
| <a name="input_create_iam_role"></a> [create\_iam\_role](#input\_create\_iam\_role) | Determines whether a an IAM role is created or to use an existing IAM role | `bool` | `true` | no |
| <a name="input_create_iam_role"></a> [create\_iam\_role](#input\_create\_iam\_role) | Determines whether an IAM role is created for the cluster | `bool` | `true` | no |
| <a name="input_create_kms_key"></a> [create\_kms\_key](#input\_create\_kms\_key) | Controls if a KMS key for cluster encryption should be created | `bool` | `true` | no |
| <a name="input_create_node_iam_role"></a> [create\_node\_iam\_role](#input\_create\_node\_iam\_role) | Determines whether an EKS Auto node IAM role is created | `bool` | `true` | no |
| <a name="input_create_node_security_group"></a> [create\_node\_security\_group](#input\_create\_node\_security\_group) | Determines whether to create a security group for the node groups or use the existing `node_security_group_id` | `bool` | `true` | no |
| <a name="input_custom_oidc_thumbprints"></a> [custom\_oidc\_thumbprints](#input\_custom\_oidc\_thumbprints) | Additional list of server certificate thumbprints for the OpenID Connect (OIDC) identity provider's server certificate(s) | `list(string)` | `[]` | no |
| <a name="input_dataplane_wait_duration"></a> [dataplane\_wait\_duration](#input\_dataplane\_wait\_duration) | Duration to wait after the EKS cluster has become active before creating the dataplane components (EKS managed node group(s), self-managed node group(s), Fargate profile(s)) | `string` | `"30s"` | no |
@@ -285,13 +439,15 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| <a name="input_enable_efa_support"></a> [enable\_efa\_support](#input\_enable\_efa\_support) | Determines whether to enable Elastic Fabric Adapter (EFA) support | `bool` | `false` | no |
| <a name="input_enable_irsa"></a> [enable\_irsa](#input\_enable\_irsa) | Determines whether to create an OpenID Connect Provider for EKS to enable IRSA | `bool` | `true` | no |
| <a name="input_enable_kms_key_rotation"></a> [enable\_kms\_key\_rotation](#input\_enable\_kms\_key\_rotation) | Specifies whether key rotation is enabled | `bool` | `true` | no |
| <a name="input_enable_node_custom_tags_permissions"></a> [enable\_node\_custom\_tags\_permissions](#input\_enable\_node\_custom\_tags\_permissions) | Determines whether to enable permissions for custom tags for the EKS Auto node IAM role | `bool` | `true` | no |
| <a name="input_enable_security_groups_for_pods"></a> [enable\_security\_groups\_for\_pods](#input\_enable\_security\_groups\_for\_pods) | Determines whether to add the necessary IAM permission policy for security groups for pods | `bool` | `true` | no |
| <a name="input_fargate_profile_defaults"></a> [fargate\_profile\_defaults](#input\_fargate\_profile\_defaults) | Map of Fargate Profile default configurations | `any` | `{}` | no |
| <a name="input_fargate_profiles"></a> [fargate\_profiles](#input\_fargate\_profiles) | Map of Fargate Profile definitions to create | `any` | `{}` | no |
| <a name="input_iam_role_additional_policies"></a> [iam\_role\_additional\_policies](#input\_iam\_role\_additional\_policies) | Additional policies to be added to the IAM role | `map(string)` | `{}` | no |
| <a name="input_iam_role_arn"></a> [iam\_role\_arn](#input\_iam\_role\_arn) | Existing IAM role ARN for the cluster. Required if `create_iam_role` is set to `false` | `string` | `null` | no |
| <a name="input_iam_role_description"></a> [iam\_role\_description](#input\_iam\_role\_description) | Description of the role | `string` | `null` | no |
| <a name="input_iam_role_name"></a> [iam\_role\_name](#input\_iam\_role\_name) | Name to use on IAM role created | `string` | `null` | no |
| <a name="input_iam_role_path"></a> [iam\_role\_path](#input\_iam\_role\_path) | Cluster IAM role path | `string` | `null` | no |
| <a name="input_iam_role_path"></a> [iam\_role\_path](#input\_iam\_role\_path) | The IAM role path | `string` | `null` | no |
| <a name="input_iam_role_permissions_boundary"></a> [iam\_role\_permissions\_boundary](#input\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the IAM role | `string` | `null` | no |
| <a name="input_iam_role_tags"></a> [iam\_role\_tags](#input\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no |
| <a name="input_iam_role_use_name_prefix"></a> [iam\_role\_use\_name\_prefix](#input\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`iam_role_name`) is used as a prefix | `bool` | `true` | no |
@@ -306,6 +462,14 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| <a name="input_kms_key_service_users"></a> [kms\_key\_service\_users](#input\_kms\_key\_service\_users) | A list of IAM ARNs for [key service users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-service-integration) | `list(string)` | `[]` | no |
| <a name="input_kms_key_source_policy_documents"></a> [kms\_key\_source\_policy\_documents](#input\_kms\_key\_source\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no |
| <a name="input_kms_key_users"></a> [kms\_key\_users](#input\_kms\_key\_users) | A list of IAM ARNs for [key users](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-users) | `list(string)` | `[]` | no |
| <a name="input_node_iam_role_additional_policies"></a> [node\_iam\_role\_additional\_policies](#input\_node\_iam\_role\_additional\_policies) | Additional policies to be added to the EKS Auto node IAM role | `map(string)` | `{}` | no |
| <a name="input_node_iam_role_description"></a> [node\_iam\_role\_description](#input\_node\_iam\_role\_description) | Description of the EKS Auto node IAM role | `string` | `null` | no |
| <a name="input_node_iam_role_name"></a> [node\_iam\_role\_name](#input\_node\_iam\_role\_name) | Name to use on the EKS Auto node IAM role created | `string` | `null` | no |
| <a name="input_node_iam_role_path"></a> [node\_iam\_role\_path](#input\_node\_iam\_role\_path) | The EKS Auto node IAM role path | `string` | `null` | no |
| <a name="input_node_iam_role_permissions_boundary"></a> [node\_iam\_role\_permissions\_boundary](#input\_node\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the EKS Auto node IAM role | `string` | `null` | no |
| <a name="input_node_iam_role_policy_statements"></a> [node\_iam\_role\_policy\_statements](#input\_node\_iam\_role\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no |
| <a name="input_node_iam_role_tags"></a> [node\_iam\_role\_tags](#input\_node\_iam\_role\_tags) | A map of additional tags to add to the EKS Auto node IAM role created | `map(string)` | `{}` | no |
| <a name="input_node_iam_role_use_name_prefix"></a> [node\_iam\_role\_use\_name\_prefix](#input\_node\_iam\_role\_use\_name\_prefix) | Determines whether the EKS Auto node IAM role name (`node_iam_role_name`) is used as a prefix | `bool` | `true` | no |
| <a name="input_node_security_group_additional_rules"></a> [node\_security\_group\_additional\_rules](#input\_node\_security\_group\_additional\_rules) | List of additional security group rules to add to the node security group created. Set `source_cluster_security_group = true` inside rules to set the `cluster_security_group` as source | `any` | `{}` | no |
| <a name="input_node_security_group_description"></a> [node\_security\_group\_description](#input\_node\_security\_group\_description) | Description of the node security group created | `string` | `"EKS node shared security group"` | no |
| <a name="input_node_security_group_enable_recommended_rules"></a> [node\_security\_group\_enable\_recommended\_rules](#input\_node\_security\_group\_enable\_recommended\_rules) | Determines whether to enable recommended security group rules for the node security group created. This includes node-to-node TCP ingress on ephemeral ports and allows all egress traffic | `bool` | `true` | no |
@@ -336,8 +500,8 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| <a name="output_cluster_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster |
| <a name="output_cluster_dualstack_oidc_issuer_url"></a> [cluster\_dualstack\_oidc\_issuer\_url](#output\_cluster\_dualstack\_oidc\_issuer\_url) | Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider |
| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN of the EKS cluster |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | Cluster IAM role ARN |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | Cluster IAM role name |
| <a name="output_cluster_iam_role_unique_id"></a> [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_cluster_id"></a> [cluster\_id](#output\_cluster\_id) | The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts |
| <a name="output_cluster_identity_providers"></a> [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled |
@@ -358,6 +522,9 @@ We are grateful to the community for contributing bugfixes and improvements! Ple
| <a name="output_kms_key_arn"></a> [kms\_key\_arn](#output\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key |
| <a name="output_kms_key_id"></a> [kms\_key\_id](#output\_kms\_key\_id) | The globally unique identifier for the key |
| <a name="output_kms_key_policy"></a> [kms\_key\_policy](#output\_kms\_key\_policy) | The IAM resource policy set on the key |
| <a name="output_node_iam_role_arn"></a> [node\_iam\_role\_arn](#output\_node\_iam\_role\_arn) | EKS Auto node IAM role ARN |
| <a name="output_node_iam_role_name"></a> [node\_iam\_role\_name](#output\_node\_iam\_role\_name) | EKS Auto node IAM role name |
| <a name="output_node_iam_role_unique_id"></a> [node\_iam\_role\_unique\_id](#output\_node\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_node_security_group_arn"></a> [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group |
| <a name="output_node_security_group_id"></a> [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group |
| <a name="output_oidc_provider"></a> [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) |

View File

@@ -0,0 +1,96 @@
# EKS Auto Mode
## Usage
To provision the provided configurations you need to execute:
```bash
terraform init
terraform plan
terraform apply --auto-approve
```
Once the cluster has finished provisioning, you can use the `kubectl` command to interact with the cluster. For example, to deploy a sample deployment and see EKS Auto Mode in action, run:
```bash
aws eks update-kubeconfig --name $(terraform output -raw cluster_name)
kubectl apply -f deployment.yaml
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules
| Name | Source | Version |
|------|--------|---------|
| <a name="module_disabled_eks"></a> [disabled\_eks](#module\_disabled\_eks) | ../.. | n/a |
| <a name="module_eks"></a> [eks](#module\_eks) | ../.. | n/a |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
## Resources
| Name | Type |
|------|------|
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
## Inputs
No inputs.
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_access_entries"></a> [access\_entries](#output\_access\_entries) | Map of access entries created and their attributes |
| <a name="output_cloudwatch_log_group_arn"></a> [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | Arn of cloudwatch log group created |
| <a name="output_cloudwatch_log_group_name"></a> [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of cloudwatch log group created |
| <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_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster |
| <a name="output_cluster_dualstack_oidc_issuer_url"></a> [cluster\_dualstack\_oidc\_issuer\_url](#output\_cluster\_dualstack\_oidc\_issuer\_url) | Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider |
| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | Cluster IAM role ARN |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | Cluster IAM role name |
| <a name="output_cluster_iam_role_unique_id"></a> [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_cluster_id"></a> [cluster\_id](#output\_cluster\_id) | The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts |
| <a name="output_cluster_identity_providers"></a> [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled |
| <a name="output_cluster_ip_family"></a> [cluster\_ip\_family](#output\_cluster\_ip\_family) | The IP family used by the cluster (e.g. `ipv4` or `ipv6`) |
| <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_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. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console |
| <a name="output_cluster_security_group_arn"></a> [cluster\_security\_group\_arn](#output\_cluster\_security\_group\_arn) | Amazon Resource Name (ARN) of the cluster security group |
| <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 CIDR block where Kubernetes pod and service IP addresses are assigned from |
| <a name="output_cluster_status"></a> [cluster\_status](#output\_cluster\_status) | Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED` |
| <a name="output_cluster_tls_certificate_sha1_fingerprint"></a> [cluster\_tls\_certificate\_sha1\_fingerprint](#output\_cluster\_tls\_certificate\_sha1\_fingerprint) | The SHA1 fingerprint of the public key of the cluster's certificate |
| <a name="output_eks_managed_node_groups"></a> [eks\_managed\_node\_groups](#output\_eks\_managed\_node\_groups) | Map of attribute maps for all EKS managed node groups created |
| <a name="output_eks_managed_node_groups_autoscaling_group_names"></a> [eks\_managed\_node\_groups\_autoscaling\_group\_names](#output\_eks\_managed\_node\_groups\_autoscaling\_group\_names) | List of the autoscaling group names created by EKS managed node groups |
| <a name="output_fargate_profiles"></a> [fargate\_profiles](#output\_fargate\_profiles) | Map of attribute maps for all EKS Fargate Profiles created |
| <a name="output_kms_key_arn"></a> [kms\_key\_arn](#output\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key |
| <a name="output_kms_key_id"></a> [kms\_key\_id](#output\_kms\_key\_id) | The globally unique identifier for the key |
| <a name="output_kms_key_policy"></a> [kms\_key\_policy](#output\_kms\_key\_policy) | The IAM resource policy set on the key |
| <a name="output_node_iam_role_arn"></a> [node\_iam\_role\_arn](#output\_node\_iam\_role\_arn) | EKS Auto node IAM role ARN |
| <a name="output_node_iam_role_name"></a> [node\_iam\_role\_name](#output\_node\_iam\_role\_name) | EKS Auto node IAM role name |
| <a name="output_node_iam_role_unique_id"></a> [node\_iam\_role\_unique\_id](#output\_node\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_node_security_group_arn"></a> [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group |
| <a name="output_node_security_group_id"></a> [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group |
| <a name="output_oidc_provider"></a> [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) |
| <a name="output_oidc_provider_arn"></a> [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider if `enable_irsa = true` |
| <a name="output_self_managed_node_groups"></a> [self\_managed\_node\_groups](#output\_self\_managed\_node\_groups) | Map of attribute maps for all self managed node groups created |
| <a name="output_self_managed_node_groups_autoscaling_group_names"></a> [self\_managed\_node\_groups\_autoscaling\_group\_names](#output\_self\_managed\_node\_groups\_autoscaling\_group\_names) | List of the autoscaling group names created by self-managed node groups |
<!-- END_TF_DOCS -->

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 3
selector:
matchLabels:
app: inflate
template:
metadata:
labels:
app: inflate
spec:
terminationGracePeriodSeconds: 0
containers:
- name: inflate
image: public.ecr.aws/eks-distro/kubernetes/pause:3.10
resources:
requests:
cpu: 1

View File

@@ -0,0 +1,86 @@
provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
name = "ex-${basename(path.cwd)}"
cluster_version = "1.31"
region = "us-west-2"
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
tags = {
Test = local.name
GithubRepo = "terraform-aws-eks"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# EKS Module
################################################################################
module "eks" {
source = "../.."
cluster_name = local.name
cluster_version = local.cluster_version
cluster_endpoint_public_access = true
enable_cluster_creator_admin_permissions = true
cluster_compute_config = {
enabled = true
node_pools = ["general-purpose"]
}
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
tags = local.tags
}
module "disabled_eks" {
source = "../.."
create = false
}
################################################################################
# Supporting Resources
################################################################################
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)]
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)]
intra_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 52)]
enable_nat_gateway = true
single_nat_gateway = true
public_subnet_tags = {
"kubernetes.io/role/elb" = 1
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = 1
}
tags = local.tags
}

View File

@@ -142,12 +142,12 @@ output "cluster_tls_certificate_sha1_fingerprint" {
################################################################################
output "cluster_iam_role_name" {
description = "IAM role name of the EKS cluster"
description = "Cluster IAM role name"
value = module.eks.cluster_iam_role_name
}
output "cluster_iam_role_arn" {
description = "IAM role ARN of the EKS cluster"
description = "Cluster IAM role ARN"
value = module.eks.cluster_iam_role_arn
}
@@ -156,6 +156,25 @@ output "cluster_iam_role_unique_id" {
value = module.eks.cluster_iam_role_unique_id
}
################################################################################
# EKS Auto Node IAM Role
################################################################################
output "node_iam_role_name" {
description = "EKS Auto node IAM role name"
value = module.eks.node_iam_role_name
}
output "node_iam_role_arn" {
description = "EKS Auto node IAM role ARN"
value = module.eks.node_iam_role_arn
}
output "node_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = module.eks.node_iam_role_unique_id
}
################################################################################
# EKS Addons
################################################################################

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

2
examples/eks-hybrid-nodes/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.pem
*.sh

View File

@@ -0,0 +1,82 @@
# EKS Hybrid Node IAM Role
## Usage
> [!NOTE]
> The [Packer CLI](https://developer.hashicorp.com/packer/tutorials/docker-get-started/get-started-install-cli) is required to build a custom AMI for the Hybrid node used in the example.
To provision the provided configurations you need to execute:
```bash
terraform init
terraform apply -target=module.remote_node_vpc -target=local_file.key_pem --auto-approve
cd ami && packer build -var 'ssh_keypair_name=hybrid-node' -var 'ssh_private_key_file=../key.pem' . && cd -
terraform apply --auto-approve
./join.sh
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 2.16 |
| <a name="requirement_http"></a> [http](#requirement\_http) | >= 3.4 |
| <a name="requirement_local"></a> [local](#requirement\_local) | >= 2.5 |
| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 4.0 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
| <a name="provider_aws.remote"></a> [aws.remote](#provider\_aws.remote) | >= 5.79 |
| <a name="provider_helm"></a> [helm](#provider\_helm) | >= 2.16 |
| <a name="provider_http"></a> [http](#provider\_http) | >= 3.4 |
| <a name="provider_local"></a> [local](#provider\_local) | >= 2.5 |
## Modules
| Name | Source | Version |
|------|--------|---------|
| <a name="module_eks"></a> [eks](#module\_eks) | ../.. | n/a |
| <a name="module_eks_hybrid_node_role"></a> [eks\_hybrid\_node\_role](#module\_eks\_hybrid\_node\_role) | ../../modules/hybrid-node-role | n/a |
| <a name="module_key_pair"></a> [key\_pair](#module\_key\_pair) | terraform-aws-modules/key-pair/aws | ~> 2.0 |
| <a name="module_remote_node_vpc"></a> [remote\_node\_vpc](#module\_remote\_node\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 |
## Resources
| Name | Type |
|------|------|
| [aws_instance.hybrid_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource |
| [aws_route.peer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_route.remote_node_private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_route.remote_node_public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource |
| [aws_security_group.remote_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_ssm_activation.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_activation) | resource |
| [aws_vpc_peering_connection.remote_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection) | resource |
| [aws_vpc_peering_connection_accepter.peer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection_accepter) | resource |
| [aws_vpc_security_group_egress_rule.remote_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource |
| [aws_vpc_security_group_ingress_rule.remote_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource |
| [helm_release.cilium](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource |
| [local_file.join](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [local_file.key_pem](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [local_file.key_pub_pem](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
| [aws_ami.hybrid_node](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source |
| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [aws_availability_zones.remote](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source |
| [http_http.icanhazip](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source |
## Inputs
No inputs.
## Outputs
No outputs.
<!-- END_TF_DOCS -->

View File

@@ -0,0 +1,320 @@
locals {
timestamp = regex_replace(timestamp(), "[- TZ:]", "")
ami_name = "${var.ami_name_prefix}-${var.eks_version}-amd64-${local.timestamp}"
tags = {
SourceAMI = "{{ .SourceAMI }}"
Name = local.ami_name
Architecture = "amd64"
}
}
data "amazon-parameterstore" "this" {
name = "/aws/service/canonical/ubuntu/server-minimal/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id"
region = var.region
}
################################################################################
# EBS Source
################################################################################
source "amazon-ebs" "this" {
# AMI Configuration
dynamic "ami_block_device_mappings" {
for_each = var.ami_block_device_mappings
content {
delete_on_termination = try(ami_block_device_mappings.value.delete_on_termination, true)
device_name = try(ami_block_device_mappings.value.device_name, null)
encrypted = try(ami_block_device_mappings.value.encrypted, null)
iops = try(ami_block_device_mappings.value.iops, null)
no_device = try(ami_block_device_mappings.value.no_device, null)
snapshot_id = try(ami_block_device_mappings.value.snapshot_id, null)
throughput = try(ami_block_device_mappings.value.throughput, null)
virtual_name = try(ami_block_device_mappings.value.virtual_name, null)
volume_size = try(ami_block_device_mappings.value.volume_size, 4)
volume_type = try(ami_block_device_mappings.value.volume_type, "gp3")
kms_key_id = try(ami_block_device_mappings.value.kms_key_id, null)
}
}
ami_description = var.ami_description
ami_groups = var.ami_groups
ami_name = local.ami_name
ami_org_arns = var.ami_org_arns
ami_ou_arns = var.ami_ou_arns
ami_regions = var.ami_regions
ami_users = var.ami_users
ami_virtualization_type = var.ami_virtualization_type
deprecate_at = var.deprecate_at
ena_support = var.ena_support
encrypt_boot = var.encrypt_boot
force_deregister = var.force_deregister
force_delete_snapshot = var.force_delete_snapshot
imds_support = var.imds_support
kms_key_id = var.kms_key_id
dynamic "launch_block_device_mappings" {
for_each = length(var.launch_block_device_mappings) > 0 ? var.launch_block_device_mappings : var.ami_block_device_mappings
content {
delete_on_termination = try(launch_block_device_mappings.value.delete_on_termination, true)
device_name = try(launch_block_device_mappings.value.device_name, null)
encrypted = try(launch_block_device_mappings.value.encrypted, null)
iops = try(launch_block_device_mappings.value.iops, null)
no_device = try(launch_block_device_mappings.value.no_device, null)
snapshot_id = try(launch_block_device_mappings.value.snapshot_id, null)
throughput = try(launch_block_device_mappings.value.throughput, null)
virtual_name = try(launch_block_device_mappings.value.virtual_name, null)
volume_size = try(launch_block_device_mappings.value.volume_size, 4)
volume_type = try(launch_block_device_mappings.value.volume_type, "gp3")
}
}
region_kms_key_ids = var.region_kms_key_ids
run_volume_tags = var.run_volume_tags
skip_create_ami = var.skip_create_ami
skip_region_validation = var.skip_region_validation
skip_save_build_region = var.skip_save_build_region
sriov_support = var.sriov_support
snapshot_groups = var.snapshot_groups
snapshot_tags = var.snapshot_tags
snapshot_users = var.snapshot_users
tags = merge(local.tags, var.tags)
# Access Configuration
access_key = var.access_key
dynamic "assume_role" {
for_each = length(var.assume_role) > 0 ? [var.assume_role] : []
content {
duration_seconds = try(assume_role.value.duration_seconds, null)
external_id = try(assume_role.value.external_id, null)
policy = try(assume_role.value.policy, null)
policy_arns = try(assume_role.value.policy_arns, null)
role_arn = try(assume_role.value.role_arn, null)
session_name = try(assume_role.value.session_name, null)
tag = try(assume_role.value.tag, null)
transitive_tag_keys = try(assume_role.value.transitive_tag_keys, null)
}
}
dynamic "aws_polling" {
for_each = length(var.aws_polling) > 0 ? [var.aws_polling] : []
content {
delay_seconds = try(aws_polling.value.delay_seconds, null)
max_attempts = try(aws_polling.value.max_attempts, null)
}
}
custom_endpoint_ec2 = var.custom_endpoint_ec2
decode_authorization_messages = var.decode_authorization_messages
insecure_skip_tls_verify = var.insecure_skip_tls_verify
max_retries = var.max_retries
mfa_code = var.mfa_code
profile = var.profile
region = var.region
secret_key = var.secret_key
shared_credentials_file = var.shared_credentials_file
skip_credential_validation = var.skip_credential_validation
skip_metadata_api_check = var.skip_metadata_api_check
token = var.token
# Communicator
communicator = var.communicator
pause_before_connecting = var.pause_before_connecting
ssh_agent_auth = var.ssh_agent_auth
ssh_bastion_agent_auth = var.ssh_bastion_agent_auth
ssh_bastion_certificate_file = var.ssh_bastion_certificate_file
ssh_bastion_host = var.ssh_bastion_host
ssh_bastion_interactive = var.ssh_bastion_interactive
ssh_bastion_password = var.ssh_bastion_password
ssh_bastion_port = var.ssh_bastion_port
ssh_bastion_private_key_file = var.ssh_bastion_private_key_file
ssh_bastion_username = var.ssh_bastion_username
ssh_ciphers = var.ssh_ciphers
ssh_certificate_file = var.ssh_certificate_file
ssh_clear_authorized_keys = var.ssh_clear_authorized_keys
ssh_disable_agent_forwarding = var.ssh_disable_agent_forwarding
ssh_file_transfer_method = var.ssh_file_transfer_method
ssh_handshake_attempts = var.ssh_handshake_attempts
ssh_host = var.ssh_host
ssh_interface = var.ssh_interface # "public_dns"
ssh_keep_alive_interval = var.ssh_keep_alive_interval
ssh_key_exchange_algorithms = var.ssh_key_exchange_algorithms
ssh_keypair_name = var.ssh_keypair_name
ssh_local_tunnels = var.ssh_local_tunnels
ssh_password = var.ssh_password
ssh_port = var.ssh_port
ssh_private_key_file = var.ssh_private_key_file
ssh_proxy_host = var.ssh_proxy_host
ssh_proxy_password = var.ssh_proxy_password
ssh_proxy_port = var.ssh_proxy_port
ssh_proxy_username = var.ssh_proxy_username
ssh_pty = var.ssh_pty
ssh_read_write_timeout = var.ssh_read_write_timeout
ssh_remote_tunnels = var.ssh_remote_tunnels
ssh_timeout = var.ssh_timeout
ssh_username = var.ssh_username
temporary_key_pair_bits = var.temporary_key_pair_bits
temporary_key_pair_type = var.temporary_key_pair_type
# Run Configuration
associate_public_ip_address = var.associate_public_ip_address
capacity_reservation_preference = var.capacity_reservation_preference
capacity_reservation_group_arn = var.capacity_reservation_group_arn
capacity_reservation_id = var.capacity_reservation_id
disable_stop_instance = var.disable_stop_instance
ebs_optimized = var.ebs_optimized
enable_nitro_enclave = var.enable_nitro_enclave
enable_unlimited_credits = var.enable_unlimited_credits
iam_instance_profile = var.iam_instance_profile
instance_type = var.instance_type
fleet_tags = var.fleet_tags
pause_before_ssm = var.pause_before_ssm
dynamic "placement" {
for_each = length(var.placement) > 0 ? [var.placement] : []
content {
host_resource_group_arn = try(placement.value.host_resource_group_arn, null)
tenancy = try(placement.value.tenancy, null)
}
}
run_tags = merge(local.tags, var.run_tags)
security_group_ids = var.security_group_ids
dynamic "security_group_filter" {
for_each = length(var.security_group_filter) > 0 ? var.security_group_filter : []
content {
filters = try(security_group_filter.value.filters, null)
}
}
session_manager_port = var.session_manager_port
shutdown_behavior = var.shutdown_behavior
skip_profile_validation = var.skip_profile_validation
source_ami = data.amazon-parameterstore.this.value
dynamic "subnet_filter" {
for_each = length(var.subnet_filter) > 0 ? [var.subnet_filter] : []
content {
filters = try(subnet_filter.value.filters, null)
most_free = try(subnet_filter.value.most_free, null)
random = try(subnet_filter.value.random, null)
}
}
subnet_id = var.subnet_id
dynamic "temporary_iam_instance_profile_policy_document" {
for_each = length(var.temporary_iam_instance_profile_policy_document) > 0 ? [var.temporary_iam_instance_profile_policy_document] : []
content {
dynamic "Statement" {
for_each = temporary_iam_instance_profile_policy_document.value
content {
Action = try(Statement.value.Action, [])
Effect = try(Statement.value.Effect, "Allow")
Resource = try(Statement.value.Resource, ["*"])
}
}
Version = "2012-10-17"
}
}
temporary_security_group_source_cidrs = var.temporary_security_group_source_cidrs
temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip
user_data = var.user_data
user_data_file = var.user_data_file
dynamic "vpc_filter" {
for_each = length(var.vpc_filter) > 0 ? var.vpc_filter : []
content {
filters = try(vpc_filter.value.filters, null)
}
}
vpc_id = var.vpc_id
dynamic "metadata_options" {
for_each = length(var.metadata_options) > 0 ? [var.metadata_options] : []
content {
http_endpoint = try(metadata_options.value.http_endpoint, 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)
}
}
}
################################################################################
# Build
################################################################################
build {
sources = ["source.amazon-ebs.this"]
provisioner "shell" {
execute_command = "echo 'packer' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
env = {
DEBIAN_FRONTEND = "noninteractive"
}
expect_disconnect = true
inline = [
"cloud-init status --wait",
"apt update",
"apt upgrade -y",
"apt install iptables conntrack -y",
"systemctl reboot",
]
pause_after = "15s"
}
provisioner "shell" {
execute_command = "echo 'packer' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
env = {
DEBIAN_FRONTEND = "noninteractive"
}
inline = [
"snap install aws-cli --classic",
"snap switch --channel=candidate amazon-ssm-agent",
"curl -OL 'https://hybrid-assets.eks.amazonaws.com/releases/latest/bin/linux/amd64/nodeadm'",
"mv nodeadm /usr/bin/nodeadm",
"chmod +x /usr/bin/nodeadm",
"nodeadm install ${var.eks_version} --credential-provider ${var.credential_provider}",
]
}
provisioner "shell" {
execute_command = "echo 'packer' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
env = {
DEBIAN_FRONTEND = "noninteractive"
}
inline = [
"apt --purge autoremove -y",
"cloud-init clean --logs --machine-id",
"mkdir -p /etc/amazon/ssm",
"cp $(find / -name '*seelog.xml.template') /etc/amazon/ssm/seelog.xml",
]
}
}

View File

@@ -0,0 +1,8 @@
packer {
required_plugins {
amazon = {
version = "~> 1.2"
source = "github.com/hashicorp/amazon"
}
}
}

View File

@@ -0,0 +1,723 @@
variable "ami_name_prefix" {
description = "The prefix to use when creating the AMI name. i.e. - `<ami_name_prefix>-<eks_version>-<architecture>-<timestamp>"
type = string
default = "eks-hybrid-ubuntu"
}
variable "eks_version" {
description = "The EKS cluster version associated with the AMI created"
type = string
default = "1.31"
}
variable "credential_provider" {
description = "The credential provider to use with the Hybrid Node role"
type = string
default = "ssm"
}
variable "cpu_architecture" {
description = "The CPU architecture. Either `amd64` or `arm64`"
type = string
default = "amd64"
}
################################################################################
# EBS Source
################################################################################
variable "ami_block_device_mappings" {
description = "The block device mappings attached when booting a new instance from the AMI created"
type = list(map(string))
default = [
{
device_name = "/dev/sda1"
volume_size = 24
volume_type = "gp3"
delete_on_termination = true
},
]
}
variable "ami_description" {
description = "The description to use when creating the AMI"
type = string
default = "EKS Hybrid Node demonstration AMI"
}
variable "ami_groups" {
description = "A list of groups that have access to launch the resulting AMI(s). By default no groups have permission to launch the AMI. `all` will make the AMI publicly accessible. AWS currently doesn't accept any value other than `all`"
type = list(string)
default = null
}
variable "ami_org_arns" {
description = "A list of Amazon Resource Names (ARN) of AWS Organizations that have access to launch the resulting AMI(s). By default no organizations have permission to launch the AMI"
type = list(string)
default = null
}
variable "ami_ou_arns" {
description = "A list of Amazon Resource Names (ARN) of AWS Organizations organizational units (OU) that have access to launch the resulting AMI(s). By default no organizational units have permission to launch the AMI"
type = list(string)
default = null
}
variable "ami_regions" {
description = "A list of regions to copy the AMI to. Tags and attributes are copied along with the AMI. AMI copying takes time depending on the size of the AMI, but will generally take many minutes"
type = list(string)
default = null
}
variable "ami_users" {
description = "A list of account IDs that have access to launch the resulting AMI(s). By default no additional users other than the user creating the AMI has permissions to launch it"
type = list(string)
default = null
}
variable "ami_virtualization_type" {
description = "The type of virtualization used to create the AMI. Can be one of `hvm` or `paravirtual`"
type = string
default = "hvm"
}
variable "deprecate_at" {
description = "The date and time to deprecate the AMI, in UTC, in the following format: YYYY-MM-DDTHH:MM:SSZ. If you specify a value for seconds, Amazon EC2 rounds the seconds to the nearest minute"
type = string
default = null
}
variable "ena_support" {
description = "Enable enhanced networking (ENA but not SriovNetSupport) on HVM-compatible AMIs"
type = bool
default = null
}
variable "encrypt_boot" {
description = "Whether or not to encrypt the resulting AMI when copying a provisioned instance to an AMI. By default, Packer will keep the encryption setting to what it was in the source image"
type = bool
default = null
}
variable "force_deregister" {
description = "Force Packer to first deregister an existing AMI if one with the same name already exists. Default `false`"
type = bool
default = null
}
variable "force_delete_snapshot" {
description = "Force Packer to delete snapshots associated with AMIs, which have been deregistered by force_deregister. Default `false`"
type = bool
default = null
}
variable "imds_support" {
description = "Enforce version of the Instance Metadata Service on the built AMI. Valid options are `unset` (legacy) and `v2.0`"
type = string
default = "v2.0"
}
variable "kms_key_id" {
description = "ID, alias or ARN of the KMS key to use for AMI encryption. This only applies to the main `region` -- any regions the AMI gets copied to copied will be encrypted by the default EBS KMS key for that region, unless you set region-specific keys in `region_kms_key_ids`"
type = string
default = null
}
variable "launch_block_device_mappings" {
description = "The block device mappings to use when creating the AMI. If you add instance store volumes or EBS volumes in addition to the root device volume, the created AMI will contain block device mapping information for those volumes. Amazon creates snapshots of the source instance's root volume and any other EBS volumes described here. When you launch an instance from this new AMI, the instance automatically launches with these additional volumes, and will restore them from snapshots taken from the source instance"
type = list(map(string))
default = [
{
device_name = "/dev/sda1"
volume_size = 24
volume_type = "gp3"
delete_on_termination = true
},
]
}
variable "region_kms_key_ids" {
description = "regions to copy the ami to, along with the custom kms key id (alias or arn) to use for encryption for that region. Keys must match the regions provided in `ami_regions`"
type = map(string)
default = null
}
variable "run_volume_tags" {
description = "Tags to apply to the volumes that are launched to create the AMI. These tags are not applied to the resulting AMI"
type = map(string)
default = null
}
variable "skip_create_ami" {
description = "If `true`, Packer will not create the AMI. Useful for setting to `true` during a build test stage. Default `false`"
type = bool
default = null
}
variable "skip_region_validation" {
description = "Set to `true` if you want to skip validation of the `ami_regions` configuration option. Default `false`"
type = bool
default = null
}
variable "skip_save_build_region" {
description = "If true, Packer will not check whether an AMI with the ami_name exists in the region it is building in. It will use an intermediary AMI name, which it will not convert to an AMI in the build region. Default `false`"
type = bool
default = null
}
variable "sriov_support" {
description = "Enable enhanced networking (SriovNetSupport but not ENA) on HVM-compatible AMIs"
type = bool
default = null
}
variable "snapshot_groups" {
description = "A list of groups that have access to create volumes from the snapshot(s). By default no groups have permission to create volumes from the snapshot(s). all will make the snapshot publicly accessible"
type = list(string)
default = null
}
variable "snapshot_tags" {
description = "Key/value pair tags to apply to snapshot. They will override AMI tags if already applied to snapshot"
type = map(string)
default = null
}
variable "snapshot_users" {
description = "A list of account IDs that have access to create volumes from the snapshot(s). By default no additional users other than the user creating the AMI has permissions to create volumes from the backing snapshot(s)"
type = list(string)
default = null
}
variable "tags" {
description = "Key/value pair tags applied to the AMI"
type = map(string)
default = {}
}
# Access Configuration
variable "access_key" {
description = "The access key used to communicate with AWS"
type = string
default = null
}
variable "assume_role" {
description = "If provided with a role ARN, Packer will attempt to assume this role using the supplied credentials"
type = map(string)
default = {}
}
variable "aws_polling" {
description = "Polling configuration for the AWS waiter. Configures the waiter for resources creation or actions like attaching volumes or importing image"
type = map(string)
default = {}
}
variable "custom_endpoint_ec2" {
description = "This option is useful if you use a cloud provider whose API is compatible with aws EC2"
type = string
default = null
}
variable "decode_authorization_messages" {
description = "Enable automatic decoding of any encoded authorization (error) messages using the sts:DecodeAuthorizationMessage API"
type = bool
default = null
}
variable "insecure_skip_tls_verify" {
description = "This allows skipping TLS verification of the AWS EC2 endpoint. The default is `false`"
type = bool
default = null
}
variable "max_retries" {
description = "This is the maximum number of times an API call is retried, in the case where requests are being throttled or experiencing transient failures. The delay between the subsequent API calls increases exponentially"
type = number
default = null
}
variable "mfa_code" {
description = "The MFA TOTP code. This should probably be a user variable since it changes all the time"
type = string
default = null
}
variable "profile" {
description = "The profile to use in the shared credentials file for AWS"
type = string
default = null
}
variable "region" {
description = "The name of the region, such as us-east-1, in which to launch the EC2 instance to create the AMI"
type = string
default = "us-east-1"
}
variable "secret_key" {
description = "The secret key used to communicate with AWS"
type = string
default = null
}
variable "shared_credentials_file" {
description = "Path to a credentials file to load credentials from"
type = string
default = null
}
variable "skip_credential_validation" {
description = "Set to true if you want to skip validating AWS credentials before runtime"
type = bool
default = null
}
variable "skip_metadata_api_check" {
description = "Skip Metadata Api Check"
type = bool
default = null
}
variable "token" {
description = "The access token to use. This is different from the access key and secret key"
type = string
default = null
}
# Communicator
variable "communicator" {
description = "The communicator to use to communicate with the EC2 instance. Valid values are `none`, `ssh`, `winrm`, and `ssh+winrm`"
type = string
default = "ssh"
}
variable "pause_before_connecting" {
description = "We recommend that you enable SSH or WinRM as the very last step in your guest's bootstrap script, but sometimes you may have a race condition where you need Packer to wait before attempting to connect to your guest"
type = string
default = null
}
variable "ssh_agent_auth" {
description = "If true, the local SSH agent will be used to authenticate connections to the source instance. No temporary keypair will be created, and the values of `ssh_password` and `ssh_private_key_file` will be ignored. The environment variable `SSH_AUTH_SOCK` must be set for this option to work properly"
type = bool
default = null
}
variable "ssh_bastion_agent_auth" {
description = "If `true`, the local SSH agent will be used to authenticate with the bastion host. Defaults to `false`"
type = bool
default = null
}
variable "ssh_bastion_certificate_file" {
description = "Path to user certificate used to authenticate with bastion host. The ~ can be used in path and will be expanded to the home directory of current user"
type = string
default = null
}
variable "ssh_bastion_host" {
description = "A bastion host to use for the actual SSH connection"
type = string
default = null
}
variable "ssh_bastion_interactive" {
description = "If `true`, the keyboard-interactive used to authenticate with bastion host"
type = bool
default = null
}
variable "ssh_bastion_password" {
description = "The password to use to authenticate with the bastion host"
type = string
default = null
}
variable "ssh_bastion_port" {
description = "The port of the bastion host. Defaults to `22`"
type = number
default = null
}
variable "ssh_bastion_private_key_file" {
description = "Path to a PEM encoded private key file to use to authenticate with the bastion host. The `~` can be used in path and will be expanded to the home directory of current user"
type = string
default = null
}
variable "ssh_bastion_username" {
description = "The username to connect to the bastion host"
type = string
default = null
}
variable "ssh_ciphers" {
description = "This overrides the value of ciphers supported by default by Golang. The default value is `[\"aes128-gcm@openssh.com\", \"chacha20-poly1305@openssh.com\", \"aes128-ctr\", \"aes192-ctr\", \"aes256-ctr\"]`"
type = list(string)
default = null
}
variable "ssh_certificate_file" {
description = "Path to user certificate used to authenticate with SSH. The `~` can be used in path and will be expanded to the home directory of current user"
type = string
default = null
}
variable "ssh_clear_authorized_keys" {
description = "If true, Packer will attempt to remove its temporary key from `~/.ssh/authorized_keys` and `/root/.ssh/authorized_keys`"
type = bool
default = null
}
variable "ssh_disable_agent_forwarding" {
description = "If `true`, SSH agent forwarding will be disabled. Defaults to `false`"
type = bool
default = null
}
variable "ssh_file_transfer_method" {
description = "How to transfer files, Secure copy (`scp` default) or SSH File Transfer Protocol (`sftp`)"
type = string
default = null
}
variable "ssh_handshake_attempts" {
description = "The number of handshakes to attempt with SSH once it can connect. This defaults to `10`, unless a `ssh_timeout` is set"
type = number
default = null
}
variable "ssh_host" {
description = "The address to SSH to. This usually is automatically configured by the builder"
type = string
default = null
}
variable "ssh_interface" {
description = "One of `public_ip`, `private_ip`, `public_dns`, `private_dns` or `session_manager`. If set, either the public IP address, private IP address, public DNS name or private DNS name will be used as the host for SSH. The default behavior if inside a VPC is to use the public IP address if available, otherwise the private IP address will be used. If not in a VPC the public DNS name will be used"
type = string
default = "public_ip"
}
variable "ssh_keep_alive_interval" {
description = "How often to send \"keep alive\" messages to the server. Set to a negative value (`-1s`) to disable. Defaults to `5s`"
type = string
default = null
}
variable "ssh_key_exchange_algorithms" {
description = "If set, Packer will override the value of key exchange (kex) algorithms supported by default by Golang. Acceptable values include: `curve25519-sha256@libssh.org`, `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `diffie-hellman-group14-sha1`, and `diffie-hellman-group1-sha1`"
type = list(string)
default = null
}
variable "ssh_keypair_name" {
description = "If specified, this is the key that will be used for SSH with the machine. The key must match a key pair name loaded up into the remote"
type = string
default = null
}
variable "ssh_local_tunnels" {
description = "A list of local tunnels to use when connecting to the host"
type = list(string)
default = null
}
variable "ssh_password" {
description = "A plaintext password to use to authenticate with SSH"
type = string
default = null
}
variable "ssh_port" {
description = "The port to connect to SSH. This defaults to `22`"
type = number
default = null
}
variable "ssh_private_key_file" {
description = "Path to a PEM encoded private key file to use to authenticate with SSH. The ~ can be used in path and will be expanded to the home directory of current user"
type = string
default = null
}
variable "ssh_proxy_host" {
description = "A SOCKS proxy host to use for SSH connection"
type = string
default = null
}
variable "ssh_proxy_password" {
description = "The optional password to use to authenticate with the proxy server"
type = string
default = null
}
variable "ssh_proxy_port" {
description = "A port of the SOCKS proxy. Defaults to `1080`"
type = number
default = null
}
variable "ssh_proxy_username" {
description = "The optional username to authenticate with the proxy server"
type = string
default = null
}
variable "ssh_pty" {
description = "If `true`, a PTY will be requested for the SSH connection. This defaults to `false`"
type = bool
default = null
}
variable "ssh_read_write_timeout" {
description = "The amount of time to wait for a remote command to end. This might be useful if, for example, packer hangs on a connection after a reboot. Example: `5m`. Disabled by default"
type = string
default = null
}
variable "ssh_remote_tunnels" {
description = "A list of remote tunnels to use when connecting to the host"
type = list(string)
default = null
}
variable "ssh_timeout" {
description = "The time to wait for SSH to become available. Packer uses this to determine when the machine has booted so this is usually quite long. This defaults to `5m`, unless `ssh_handshake_attempts` is set"
type = string
default = null
}
variable "ssh_username" {
description = "The username to connect to SSH with. Required if using SSH"
type = string
default = "ubuntu"
}
variable "temporary_key_pair_type" {
description = "Specifies the type of key to create. The possible values are 'dsa', 'ecdsa', 'ed25519', or 'rsa'. Default is `ed25519`"
type = string
default = "ed25519"
}
variable "temporary_key_pair_bits" {
description = "Specifies the number of bits in the key to create. For RSA keys, the minimum size is 1024 bits and the default is 4096 bits. Generally, 3072 bits is considered sufficient"
type = number
default = null
}
# Run Configuration
variable "associate_public_ip_address" {
description = "If using a non-default VPC, public IP addresses are not provided by default. If this is true, your new instance will get a Public IP"
type = bool
default = true
}
variable "capacity_reservation_preference" {
description = "Set the preference for using a capacity reservation if one exists. Either will be `open` or `none`. Defaults to `none`"
type = string
default = null
}
variable "capacity_reservation_group_arn" {
description = "Provide the EC2 Capacity Reservation Group ARN that will be used by Packer"
type = string
default = null
}
variable "capacity_reservation_id" {
description = "Provide the specific EC2 Capacity Reservation ID that will be used by Packer"
type = string
default = null
}
variable "disable_stop_instance" {
description = "If this is set to true, Packer will not stop the instance but will assume that you will send the stop signal yourself through your final provisioner"
type = bool
default = null
}
variable "ebs_optimized" {
description = "Mark instance as EBS Optimized. Default `false`"
type = bool
default = null
}
variable "enable_nitro_enclave" {
description = "Enable support for Nitro Enclaves on the instance"
type = bool
default = null
}
variable "enable_unlimited_credits" {
description = "Enabling Unlimited credits allows the source instance to burst additional CPU beyond its available CPU Credits for as long as the demand exists"
type = bool
default = null
}
variable "iam_instance_profile" {
description = "The name of an IAM instance profile to launch the EC2 instance with"
type = string
default = null
}
variable "instance_type" {
description = "The EC2 instance type to use while building the AMI, such as `m5.large`"
type = string
default = "c5.xlarge"
}
variable "fleet_tags" {
description = "Key/value pair tags to apply tags to the fleet that is issued"
type = map(string)
default = null
}
variable "pause_before_ssm" {
description = "The time to wait before establishing the Session Manager session"
type = string
default = null
}
variable "placement" {
description = "Describes the placement of an instance"
type = map(string)
default = {}
}
variable "run_tags" {
description = "Key/value pair tags to apply to the generated key-pair, security group, iam profile and role, snapshot, network interfaces and instance that is launched to create the EBS volumes. The resulting AMI will also inherit these tags"
type = map(string)
default = null
}
variable "security_group_ids" {
description = "A list of security group IDs to assign to the instance. By default this is not set and Packer will automatically create a new temporary security group to allow SSH access"
type = list(string)
default = null
}
variable "security_group_filter" {
description = "Filters used to populate the `security_group_ids` field. `security_group_ids` take precedence over this"
type = list(map(string))
default = []
}
variable "session_manager_port" {
description = "Which port to connect the local end of the session tunnel to. If left blank, Packer will choose a port for you from available ports. This option is only used when `ssh_interface` is set `session_manager`"
type = number
default = null
}
variable "shutdown_behavior" {
description = "Automatically terminate instances on shutdown in case Packer exits ungracefully. Possible values are `stop` and `terminate`. Defaults to `stop`"
type = string
default = null
}
variable "skip_profile_validation" {
description = "Whether or not to check if the IAM instance profile exists. Defaults to `false`"
type = bool
default = null
}
variable "subnet_filter" {
description = "Filters used to populate the subnet_id field. `subnet_id` take precedence over this"
default = {
filters = {
"tag:eks-hybrid-packer" = "true"
}
random = true
}
}
variable "subnet_id" {
description = "f using VPC, the ID of the subnet, such as subnet-12345def, where Packer will launch the EC2 instance. This field is required if you are using an non-default VPC"
type = string
default = null
}
variable "temporary_iam_instance_profile_policy_document" {
description = "Creates a temporary instance profile policy document to grant permissions to the EC2 instance. This is an alternative to using an existing `iam_instance_profile`"
default = [
{
Effect = "Allow"
Action = [
"ec2:Describe*",
]
Resource = ["*"]
},
]
}
variable "temporary_security_group_source_cidrs" {
description = "A list of IPv4 CIDR blocks to be authorized access to the instance, when packer is creating a temporary security group. The default is `[0.0.0.0/0]`"
type = list(string)
default = null
}
variable "temporary_security_group_source_public_ip" {
description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Defaults to `false`"
type = bool
default = null
}
variable "user_data" {
description = "User data to apply when launching the instance"
type = string
default = null
}
variable "user_data_file" {
description = "Path to a file that will be used for the user data when launching the instance"
type = string
default = null
}
variable "vpc_filter" {
description = "Filters used to populate the `vpc_id` field. `vpc_id` take precedence over this"
type = list(map(string))
default = []
}
variable "vpc_id" {
description = "If launching into a VPC subnet, Packer needs the VPC ID in order to create a temporary security group within the VPC. Requires `subnet_id` to be set. If this field is left blank, Packer will try to get the VPC ID from the `subnet_id`"
type = string
default = null
}
variable "metadata_options" {
description = "Configures the metadata options for the instance launched"
type = map(string)
default = {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
}
################################################################################
# Build
################################################################################
variable "shell_provisioner1" {
description = "Values passed to the first shell provisioner"
default = {}
}
variable "shell_provisioner2" {
description = "Values passed to the second shell provisioner"
default = {}
}
variable "shell_provisioner3" {
description = "Values passed to the third/last shell provisioner"
default = {}
}

View File

@@ -0,0 +1,148 @@
provider "aws" {
region = local.region
}
provider "helm" {
kubernetes {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
exec {
api_version = "client.authentication.k8s.io/v1beta1"
command = "aws"
# This requires the awscli to be installed locally where Terraform is executed
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
}
}
}
locals {
name = "ex-${basename(path.cwd)}"
region = "us-west-2"
cluster_version = "1.31"
tags = {
Test = local.name
GithubRepo = "terraform-aws-eks"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# EKS Cluster
################################################################################
module "eks" {
source = "../.."
cluster_name = local.name
cluster_version = local.cluster_version
cluster_endpoint_public_access = true
enable_cluster_creator_admin_permissions = true
cluster_addons = {
coredns = {}
eks-pod-identity-agent = {}
kube-proxy = {}
}
create_node_security_group = false
cluster_security_group_additional_rules = {
hybrid-all = {
cidr_blocks = [local.remote_network_cidr]
description = "Allow all traffic from remote node/pod network"
from_port = 0
to_port = 0
protocol = "all"
type = "ingress"
}
}
cluster_compute_config = {
enabled = true
node_pools = ["system"]
}
access_entries = {
hybrid-node-role = {
principal_arn = module.eks_hybrid_node_role.arn
type = "HYBRID_LINUX"
}
}
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
cluster_remote_network_config = {
remote_node_networks = {
cidrs = [local.remote_node_cidr]
}
remote_pod_networks = {
cidrs = [local.remote_pod_cidr]
}
}
tags = local.tags
}
################################################################################
# VPC
################################################################################
locals {
vpc_cidr = "10.0.0.0/16"
azs = slice(data.aws_availability_zones.available.names, 0, 3)
}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = local.name
cidr = local.vpc_cidr
azs = local.azs
private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)]
public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)]
intra_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 52)]
enable_nat_gateway = true
single_nat_gateway = true
public_subnet_tags = {
"kubernetes.io/role/elb" = 1
}
private_subnet_tags = {
"kubernetes.io/role/internal-elb" = 1
}
tags = local.tags
}
################################################################################
# VPC Peering Connection
################################################################################
resource "aws_vpc_peering_connection_accepter" "peer" {
vpc_peering_connection_id = aws_vpc_peering_connection.remote_node.id
auto_accept = true
tags = local.tags
}
resource "aws_route" "peer" {
route_table_id = one(module.vpc.private_route_table_ids)
destination_cidr_block = local.remote_network_cidr
vpc_peering_connection_id = aws_vpc_peering_connection.remote_node.id
}

View File

View File

@@ -0,0 +1,314 @@
provider "aws" {
alias = "remote"
region = "us-east-1"
}
################################################################################
# Hybrid Node IAM Module
################################################################################
module "eks_hybrid_node_role" {
source = "../../modules/hybrid-node-role"
tags = local.tags
}
################################################################################
# Psuedo Hybrid Node
# Demonstration only - AWS EC2 instances are not supported for EKS Hybrid nodes
################################################################################
# Activation should be done is same region as cluster
resource "aws_ssm_activation" "this" {
name = "hybrid-node"
iam_role = module.eks_hybrid_node_role.name
registration_limit = 10
tags = local.tags
}
module "key_pair" {
source = "terraform-aws-modules/key-pair/aws"
version = "~> 2.0"
providers = {
aws = aws.remote
}
key_name = "hybrid-node"
create_private_key = true
tags = local.tags
}
resource "local_file" "key_pem" {
content = module.key_pair.private_key_pem
filename = "key.pem"
file_permission = "0600"
}
resource "local_file" "key_pub_pem" {
content = module.key_pair.public_key_pem
filename = "key_pub.pem"
file_permission = "0600"
}
resource "local_file" "join" {
content = <<-EOT
#!/usr/bin/env bash
cat <<EOF > nodeConfig.yaml
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
cluster:
name: ${module.eks.cluster_name}
region: ${local.region}
hybrid:
ssm:
activationCode: ${aws_ssm_activation.this.activation_code}
activationId: ${aws_ssm_activation.this.id}
EOF
# Use SCP/SSH to execute commands on the remote host
scp -i ${local_file.key_pem.filename} nodeConfig.yaml ubuntu@${aws_instance.hybrid_node["one"].public_ip}:/home/ubuntu/nodeConfig.yaml
ssh -n -i ${local_file.key_pem.filename} ubuntu@${aws_instance.hybrid_node["one"].public_ip} sudo nodeadm init -c file://nodeConfig.yaml
ssh -n -i ${local_file.key_pem.filename} ubuntu@${aws_instance.hybrid_node["one"].public_ip} sudo systemctl daemon-reload
scp -i ${local_file.key_pem.filename} nodeConfig.yaml ubuntu@${aws_instance.hybrid_node["two"].public_ip}:/home/ubuntu/nodeConfig.yaml
ssh -n -i ${local_file.key_pem.filename} ubuntu@${aws_instance.hybrid_node["two"].public_ip} sudo nodeadm init -c file://nodeConfig.yaml
ssh -n -i ${local_file.key_pem.filename} ubuntu@${aws_instance.hybrid_node["two"].public_ip} sudo systemctl daemon-reload
# Clean up
rm nodeConfig.yaml
EOT
filename = "join.sh"
}
data "aws_ami" "hybrid_node" {
provider = aws.remote
most_recent = true
name_regex = "eks-hybrid-ubuntu-${local.cluster_version}-amd64-*"
owners = ["self"]
}
# Demonstration only - AWS EC2 instances are not supported for EKS Hybrid nodes
resource "aws_instance" "hybrid_node" {
provider = aws.remote
for_each = { one = 0, two = 1 }
ami = data.aws_ami.hybrid_node.id
associate_public_ip_address = true
instance_type = "m5.large"
# Block IMDS to make instance look less like EC2 and more like vanilla VM
metadata_options {
http_endpoint = "disabled"
}
vpc_security_group_ids = [aws_security_group.remote_node.id]
subnet_id = element(module.remote_node_vpc.public_subnets, each.value)
tags = merge(
local.tags,
{ Name = "hybrid-node-${each.key}" }
)
}
################################################################################
# Psuedo Hybrid Node - Security Group
# Demonstration only - AWS EC2 instances are not supported for EKS Hybrid nodes
################################################################################
# Retrieve the IP of where the Terraform is running to restrict SSH access to that IP
data "http" "icanhazip" {
url = "http://icanhazip.com"
}
resource "aws_security_group" "remote_node" {
provider = aws.remote
name = "hybrid-node"
vpc_id = module.remote_node_vpc.vpc_id
revoke_rules_on_delete = true
tags = merge(
local.tags,
{ Name = "hybrid-node" }
)
}
resource "aws_vpc_security_group_ingress_rule" "remote_node" {
provider = aws.remote
for_each = {
cluster-all = {
description = "Allow all traffic from cluster network"
cidr_ipv4 = module.vpc.vpc_cidr_block
ip_protocol = "all"
}
remote-all = {
description = "Allow all traffic from within the remote network itself"
ip_protocol = "all"
referenced_security_group_id = aws_security_group.remote_node.id
}
# Restrict SSH access to only the IP where Terraform is running
ssh = {
description = "Local SSH access to join node to cluster"
cidr_ipv4 = "${chomp(data.http.icanhazip.response_body)}/32"
from_port = "22"
ip_protocol = "tcp"
}
}
cidr_ipv4 = try(each.value.cidr_ipv4, null)
from_port = try(each.value.from_port, null)
ip_protocol = try(each.value.ip_protocol, null)
to_port = try(each.value.to_port, each.value.from_port, null)
referenced_security_group_id = try(each.value.referenced_security_group_id, null)
security_group_id = aws_security_group.remote_node.id
tags = merge(
local.tags,
{ Name = "hybrid-node-${each.key}" }
)
}
resource "aws_vpc_security_group_egress_rule" "remote_node" {
provider = aws.remote
for_each = {
all = {
description = "Allow all egress"
cidr_ipv4 = "0.0.0.0/0"
ip_protocol = "all"
}
}
cidr_ipv4 = try(each.value.cidr_ipv4, null)
from_port = try(each.value.from_port, null)
ip_protocol = try(each.value.ip_protocol, null)
to_port = try(each.value.to_port, each.value.from_port, null)
referenced_security_group_id = try(each.value.referenced_security_group_id, null)
security_group_id = aws_security_group.remote_node.id
tags = merge(
local.tags,
{ Name = "hybrid-node-${each.key}" }
)
}
################################################################################
# Cilium CNI
################################################################################
resource "helm_release" "cilium" {
name = "cilium"
repository = "https://helm.cilium.io/"
chart = "cilium"
version = "1.16.4"
namespace = "kube-system"
wait = false
values = [
<<-EOT
nodeSelector:
eks.amazonaws.com/compute-type: hybrid
ipam:
mode: cluster-pool
operator:
clusterPoolIPv4MaskSize: 26
clusterPoolIPv4PodCIDRList:
- ${local.remote_pod_cidr}
operator:
unmanagedPodWatcher:
restart: false
EOT
]
}
################################################################################
# VPC
################################################################################
locals {
remote_network_cidr = "172.16.0.0/16"
remote_node_cidr = cidrsubnet(local.remote_network_cidr, 2, 0)
remote_pod_cidr = cidrsubnet(local.remote_network_cidr, 2, 1)
remote_node_azs = slice(data.aws_availability_zones.remote.names, 0, 3)
}
data "aws_availability_zones" "remote" {
provider = aws.remote
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
module "remote_node_vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
providers = {
aws = aws.remote
}
name = local.name
cidr = local.remote_network_cidr
azs = local.remote_node_azs
private_subnets = [for k, v in local.remote_node_azs : cidrsubnet(local.remote_network_cidr, 4, k)]
public_subnets = [for k, v in local.remote_node_azs : cidrsubnet(local.remote_network_cidr, 8, k + 48)]
public_subnet_tags = {
# For building the AMI
"eks-hybrid-packer" : "true"
}
enable_nat_gateway = true
single_nat_gateway = true
tags = local.tags
}
################################################################################
# VPC Peering Connection
################################################################################
resource "aws_vpc_peering_connection" "remote_node" {
provider = aws.remote
auto_accept = false
peer_vpc_id = module.vpc.vpc_id
peer_region = local.region
vpc_id = module.remote_node_vpc.vpc_id
tags = merge(
local.tags,
{ Name = "remote-node" }
)
}
resource "aws_route" "remote_node_private" {
provider = aws.remote
route_table_id = one(module.remote_node_vpc.private_route_table_ids)
destination_cidr_block = module.vpc.vpc_cidr_block
vpc_peering_connection_id = aws_vpc_peering_connection.remote_node.id
}
resource "aws_route" "remote_node_public" {
provider = aws.remote
route_table_id = one(module.remote_node_vpc.public_route_table_ids)
destination_cidr_block = module.vpc.vpc_cidr_block
vpc_peering_connection_id = aws_vpc_peering_connection.remote_node.id
}

View File

View File

@@ -0,0 +1,26 @@
terraform {
required_version = ">= 1.3.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.79"
}
helm = {
source = "hashicorp/helm"
version = ">= 2.16"
}
http = {
source = "hashicorp/http"
version = ">= 3.4"
}
local = {
source = "hashicorp/local"
version = ">= 2.5"
}
tls = {
source = "hashicorp/tls"
version = ">= 4.0"
}
}
}

View File

@@ -2,7 +2,13 @@ provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
name = "ex-eks-mng"

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -89,7 +89,7 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | >= 2.7 |
| <a name="requirement_kubectl"></a> [kubectl](#requirement\_kubectl) | >= 2.0 |
@@ -97,8 +97,8 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws.virginia"></a> [aws.virginia](#provider\_aws.virginia) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
| <a name="provider_aws.virginia"></a> [aws.virginia](#provider\_aws.virginia) | >= 5.79 |
| <a name="provider_helm"></a> [helm](#provider\_helm) | >= 2.7 |
| <a name="provider_kubectl"></a> [kubectl](#provider\_kubectl) | >= 2.0 |
@@ -128,52 +128,5 @@ No inputs.
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_access_entries"></a> [access\_entries](#output\_access\_entries) | Map of access entries created and their attributes |
| <a name="output_cloudwatch_log_group_arn"></a> [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | Arn of cloudwatch log group created |
| <a name="output_cloudwatch_log_group_name"></a> [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of cloudwatch log group created |
| <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_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster |
| <a name="output_cluster_dualstack_oidc_issuer_url"></a> [cluster\_dualstack\_oidc\_issuer\_url](#output\_cluster\_dualstack\_oidc\_issuer\_url) | Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider |
| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN of the EKS cluster |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster |
| <a name="output_cluster_iam_role_unique_id"></a> [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_cluster_id"></a> [cluster\_id](#output\_cluster\_id) | The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts |
| <a name="output_cluster_identity_providers"></a> [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled |
| <a name="output_cluster_ip_family"></a> [cluster\_ip\_family](#output\_cluster\_ip\_family) | The IP family used by the cluster (e.g. `ipv4` or `ipv6`) |
| <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_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. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console |
| <a name="output_cluster_security_group_arn"></a> [cluster\_security\_group\_arn](#output\_cluster\_security\_group\_arn) | Amazon Resource Name (ARN) of the cluster security group |
| <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 CIDR block where Kubernetes pod and service IP addresses are assigned from |
| <a name="output_cluster_status"></a> [cluster\_status](#output\_cluster\_status) | Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED` |
| <a name="output_cluster_tls_certificate_sha1_fingerprint"></a> [cluster\_tls\_certificate\_sha1\_fingerprint](#output\_cluster\_tls\_certificate\_sha1\_fingerprint) | The SHA1 fingerprint of the public key of the cluster's certificate |
| <a name="output_eks_managed_node_groups"></a> [eks\_managed\_node\_groups](#output\_eks\_managed\_node\_groups) | Map of attribute maps for all EKS managed node groups created |
| <a name="output_eks_managed_node_groups_autoscaling_group_names"></a> [eks\_managed\_node\_groups\_autoscaling\_group\_names](#output\_eks\_managed\_node\_groups\_autoscaling\_group\_names) | List of the autoscaling group names created by EKS managed node groups |
| <a name="output_fargate_profiles"></a> [fargate\_profiles](#output\_fargate\_profiles) | Map of attribute maps for all EKS Fargate Profiles created |
| <a name="output_karpenter_event_rules"></a> [karpenter\_event\_rules](#output\_karpenter\_event\_rules) | Map of the event rules created and their attributes |
| <a name="output_karpenter_iam_role_arn"></a> [karpenter\_iam\_role\_arn](#output\_karpenter\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the controller IAM role |
| <a name="output_karpenter_iam_role_name"></a> [karpenter\_iam\_role\_name](#output\_karpenter\_iam\_role\_name) | The name of the controller IAM role |
| <a name="output_karpenter_iam_role_unique_id"></a> [karpenter\_iam\_role\_unique\_id](#output\_karpenter\_iam\_role\_unique\_id) | Stable and unique string identifying the controller IAM role |
| <a name="output_karpenter_instance_profile_arn"></a> [karpenter\_instance\_profile\_arn](#output\_karpenter\_instance\_profile\_arn) | ARN assigned by AWS to the instance profile |
| <a name="output_karpenter_instance_profile_id"></a> [karpenter\_instance\_profile\_id](#output\_karpenter\_instance\_profile\_id) | Instance profile's ID |
| <a name="output_karpenter_instance_profile_name"></a> [karpenter\_instance\_profile\_name](#output\_karpenter\_instance\_profile\_name) | Name of the instance profile |
| <a name="output_karpenter_instance_profile_unique"></a> [karpenter\_instance\_profile\_unique](#output\_karpenter\_instance\_profile\_unique) | Stable and unique string identifying the IAM instance profile |
| <a name="output_karpenter_node_iam_role_arn"></a> [karpenter\_node\_iam\_role\_arn](#output\_karpenter\_node\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the IAM role |
| <a name="output_karpenter_node_iam_role_name"></a> [karpenter\_node\_iam\_role\_name](#output\_karpenter\_node\_iam\_role\_name) | The name of the IAM role |
| <a name="output_karpenter_node_iam_role_unique_id"></a> [karpenter\_node\_iam\_role\_unique\_id](#output\_karpenter\_node\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_karpenter_queue_arn"></a> [karpenter\_queue\_arn](#output\_karpenter\_queue\_arn) | The ARN of the SQS queue |
| <a name="output_karpenter_queue_name"></a> [karpenter\_queue\_name](#output\_karpenter\_queue\_name) | The name of the created Amazon SQS queue |
| <a name="output_karpenter_queue_url"></a> [karpenter\_queue\_url](#output\_karpenter\_queue\_url) | The URL for the created Amazon SQS queue |
| <a name="output_node_security_group_arn"></a> [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group |
| <a name="output_node_security_group_id"></a> [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group |
| <a name="output_oidc_provider"></a> [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) |
| <a name="output_oidc_provider_arn"></a> [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider if `enable_irsa = true` |
| <a name="output_self_managed_node_groups"></a> [self\_managed\_node\_groups](#output\_self\_managed\_node\_groups) | Map of attribute maps for all self managed node groups created |
| <a name="output_self_managed_node_groups_autoscaling_group_names"></a> [self\_managed\_node\_groups\_autoscaling\_group\_names](#output\_self\_managed\_node\_groups\_autoscaling\_group\_names) | List of the autoscaling group names created by self-managed node groups |
No outputs.
<!-- END_TF_DOCS -->

View File

@@ -35,7 +35,14 @@ provider "kubectl" {
}
}
data "aws_availability_zones" "available" {}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
data "aws_ecrpublic_authorization_token" "token" {
provider = aws.virginia
}

View File

@@ -1,297 +0,0 @@
################################################################################
# Cluster
################################################################################
output "cluster_arn" {
description = "The Amazon Resource Name (ARN) of the cluster"
value = module.eks.cluster_arn
}
output "cluster_certificate_authority_data" {
description = "Base64 encoded certificate data required to communicate with the cluster"
value = module.eks.cluster_certificate_authority_data
}
output "cluster_endpoint" {
description = "Endpoint for your Kubernetes API server"
value = module.eks.cluster_endpoint
}
output "cluster_id" {
description = "The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts"
value = module.eks.cluster_id
}
output "cluster_name" {
description = "The name of the EKS cluster"
value = module.eks.cluster_name
}
output "cluster_oidc_issuer_url" {
description = "The URL on the EKS cluster for the OpenID Connect identity provider"
value = module.eks.cluster_oidc_issuer_url
}
output "cluster_dualstack_oidc_issuer_url" {
description = "Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider"
value = module.eks.cluster_dualstack_oidc_issuer_url
}
output "cluster_platform_version" {
description = "Platform version for the cluster"
value = module.eks.cluster_platform_version
}
output "cluster_status" {
description = "Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED`"
value = module.eks.cluster_status
}
output "cluster_primary_security_group_id" {
description = "Cluster security group that was created by Amazon EKS for the cluster. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console"
value = module.eks.cluster_primary_security_group_id
}
output "cluster_service_cidr" {
description = "The CIDR block where Kubernetes pod and service IP addresses are assigned from"
value = module.eks.cluster_service_cidr
}
output "cluster_ip_family" {
description = "The IP family used by the cluster (e.g. `ipv4` or `ipv6`)"
value = module.eks.cluster_ip_family
}
################################################################################
# Access Entry
################################################################################
output "access_entries" {
description = "Map of access entries created and their attributes"
value = module.eks.access_entries
}
################################################################################
# Security Group
################################################################################
output "cluster_security_group_arn" {
description = "Amazon Resource Name (ARN) of the cluster security group"
value = module.eks.cluster_security_group_arn
}
output "cluster_security_group_id" {
description = "ID of the cluster security group"
value = module.eks.cluster_security_group_id
}
################################################################################
# Node Security Group
################################################################################
output "node_security_group_arn" {
description = "Amazon Resource Name (ARN) of the node shared security group"
value = module.eks.node_security_group_arn
}
output "node_security_group_id" {
description = "ID of the node shared security group"
value = module.eks.node_security_group_id
}
################################################################################
# IRSA
################################################################################
output "oidc_provider" {
description = "The OpenID Connect identity provider (issuer URL without leading `https://`)"
value = module.eks.oidc_provider
}
output "oidc_provider_arn" {
description = "The ARN of the OIDC Provider if `enable_irsa = true`"
value = module.eks.oidc_provider_arn
}
output "cluster_tls_certificate_sha1_fingerprint" {
description = "The SHA1 fingerprint of the public key of the cluster's certificate"
value = module.eks.cluster_tls_certificate_sha1_fingerprint
}
################################################################################
# IAM Role
################################################################################
output "cluster_iam_role_name" {
description = "IAM role name of the EKS cluster"
value = module.eks.cluster_iam_role_name
}
output "cluster_iam_role_arn" {
description = "IAM role ARN of the EKS cluster"
value = module.eks.cluster_iam_role_arn
}
output "cluster_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = module.eks.cluster_iam_role_unique_id
}
################################################################################
# EKS Addons
################################################################################
output "cluster_addons" {
description = "Map of attribute maps for all EKS cluster addons enabled"
value = module.eks.cluster_addons
}
################################################################################
# EKS Identity Provider
################################################################################
output "cluster_identity_providers" {
description = "Map of attribute maps for all EKS identity providers enabled"
value = module.eks.cluster_identity_providers
}
################################################################################
# CloudWatch Log Group
################################################################################
output "cloudwatch_log_group_name" {
description = "Name of cloudwatch log group created"
value = module.eks.cloudwatch_log_group_name
}
output "cloudwatch_log_group_arn" {
description = "Arn of cloudwatch log group created"
value = module.eks.cloudwatch_log_group_arn
}
################################################################################
# Fargate Profile
################################################################################
output "fargate_profiles" {
description = "Map of attribute maps for all EKS Fargate Profiles created"
value = module.eks.fargate_profiles
}
################################################################################
# EKS Managed Node Group
################################################################################
output "eks_managed_node_groups" {
description = "Map of attribute maps for all EKS managed node groups created"
value = module.eks.eks_managed_node_groups
}
output "eks_managed_node_groups_autoscaling_group_names" {
description = "List of the autoscaling group names created by EKS managed node groups"
value = module.eks.eks_managed_node_groups_autoscaling_group_names
}
################################################################################
# Self Managed Node Group
################################################################################
output "self_managed_node_groups" {
description = "Map of attribute maps for all self managed node groups created"
value = module.eks.self_managed_node_groups
}
output "self_managed_node_groups_autoscaling_group_names" {
description = "List of the autoscaling group names created by self-managed node groups"
value = module.eks.self_managed_node_groups_autoscaling_group_names
}
################################################################################
# Karpenter controller IAM Role
################################################################################
output "karpenter_iam_role_name" {
description = "The name of the controller IAM role"
value = module.karpenter.iam_role_name
}
output "karpenter_iam_role_arn" {
description = "The Amazon Resource Name (ARN) specifying the controller IAM role"
value = module.karpenter.iam_role_arn
}
output "karpenter_iam_role_unique_id" {
description = "Stable and unique string identifying the controller IAM role"
value = module.karpenter.iam_role_unique_id
}
################################################################################
# Node Termination Queue
################################################################################
output "karpenter_queue_arn" {
description = "The ARN of the SQS queue"
value = module.karpenter.queue_arn
}
output "karpenter_queue_name" {
description = "The name of the created Amazon SQS queue"
value = module.karpenter.queue_name
}
output "karpenter_queue_url" {
description = "The URL for the created Amazon SQS queue"
value = module.karpenter.queue_url
}
################################################################################
# Node Termination Event Rules
################################################################################
output "karpenter_event_rules" {
description = "Map of the event rules created and their attributes"
value = module.karpenter.event_rules
}
################################################################################
# Node IAM Role
################################################################################
output "karpenter_node_iam_role_name" {
description = "The name of the IAM role"
value = module.karpenter.node_iam_role_name
}
output "karpenter_node_iam_role_arn" {
description = "The Amazon Resource Name (ARN) specifying the IAM role"
value = module.karpenter.node_iam_role_arn
}
output "karpenter_node_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = module.karpenter.node_iam_role_unique_id
}
################################################################################
# Node IAM Instance Profile
################################################################################
output "karpenter_instance_profile_arn" {
description = "ARN assigned by AWS to the instance profile"
value = module.karpenter.instance_profile_arn
}
output "karpenter_instance_profile_id" {
description = "Instance profile's ID"
value = module.karpenter.instance_profile_id
}
output "karpenter_instance_profile_name" {
description = "Name of the instance profile"
value = module.karpenter.instance_profile_name
}
output "karpenter_instance_profile_unique" {
description = "Stable and unique string identifying the IAM instance profile"
value = module.karpenter.instance_profile_unique
}

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
helm = {
source = "hashicorp/helm"

View File

@@ -2,7 +2,13 @@ provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
name = "ex-self-mng"

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

320
main.tf
View File

@@ -18,6 +18,9 @@ locals {
create_outposts_local_cluster = length(var.outpost_config) > 0
enable_cluster_encryption_config = length(var.cluster_encryption_config) > 0 && !local.create_outposts_local_cluster
auto_mode_enabled = try(var.cluster_compute_config.enabled, false)
auto_mode_nodepools_enabled = length(try(var.cluster_compute_config.node_pools, [])) > 0
}
################################################################################
@@ -31,7 +34,7 @@ resource "aws_eks_cluster" "this" {
role_arn = local.cluster_role
version = var.cluster_version
enabled_cluster_log_types = var.cluster_enabled_log_types
bootstrap_self_managed_addons = var.bootstrap_self_managed_addons
bootstrap_self_managed_addons = local.auto_mode_enabled ? coalesce(var.bootstrap_self_managed_addons, false) : var.bootstrap_self_managed_addons
access_config {
authentication_mode = var.authentication_mode
@@ -44,6 +47,16 @@ resource "aws_eks_cluster" "this" {
bootstrap_cluster_creator_admin_permissions = false
}
dynamic "compute_config" {
for_each = length(var.cluster_compute_config) > 0 ? [var.cluster_compute_config] : []
content {
enabled = try(compute_config.value.enabled, null)
node_pools = local.auto_mode_enabled ? try(compute_config.value.node_pools, []) : null
node_role_arn = local.auto_mode_enabled ? try(compute_config.value.node_role_arn, aws_iam_role.eks_auto[0].arn, null) : null
}
}
vpc_config {
security_group_ids = compact(distinct(concat(var.cluster_additional_security_group_ids, [local.cluster_security_group_id])))
subnet_ids = coalescelist(var.control_plane_subnet_ids, var.subnet_ids)
@@ -57,6 +70,14 @@ resource "aws_eks_cluster" "this" {
for_each = local.create_outposts_local_cluster ? [] : [1]
content {
dynamic "elastic_load_balancing" {
for_each = local.auto_mode_enabled ? [1] : []
content {
enabled = local.auto_mode_enabled
}
}
ip_family = var.cluster_ip_family
service_ipv4_cidr = var.cluster_service_ipv4_cidr
service_ipv6_cidr = var.cluster_service_ipv6_cidr
@@ -84,6 +105,39 @@ resource "aws_eks_cluster" "this" {
}
}
dynamic "remote_network_config" {
# Not valid on Outposts
for_each = length(var.cluster_remote_network_config) > 0 && !local.create_outposts_local_cluster ? [var.cluster_remote_network_config] : []
content {
dynamic "remote_node_networks" {
for_each = [remote_network_config.value.remote_node_networks]
content {
cidrs = remote_node_networks.value.cidrs
}
}
dynamic "remote_pod_networks" {
for_each = try([remote_network_config.value.remote_pod_networks], [])
content {
cidrs = remote_pod_networks.value.cidrs
}
}
}
}
dynamic "storage_config" {
for_each = local.auto_mode_enabled ? [1] : []
content {
block_storage {
enabled = local.auto_mode_enabled
}
}
}
dynamic "upgrade_policy" {
for_each = length(var.cluster_upgrade_policy) > 0 ? [var.cluster_upgrade_policy] : []
@@ -199,7 +253,7 @@ locals {
association_policy_arn = pol_val.policy_arn
association_access_scope_type = pol_val.access_scope.type
association_access_scope_namespaces = lookup(pol_val.access_scope, "namespaces", [])
} : k => v if !contains(["EC2_LINUX", "EC2_WINDOWS", "FARGATE_LINUX"], lookup(entry_val, "type", "STANDARD")) },
} : k => v if !contains(["EC2", "EC2_LINUX", "EC2_WINDOWS", "FARGATE_LINUX", "HYBRID_LINUX"], lookup(entry_val, "type", "STANDARD")) },
)
]
])
@@ -380,14 +434,41 @@ locals {
iam_role_policy_prefix = "arn:${local.partition}:iam::aws:policy"
cluster_encryption_policy_name = coalesce(var.cluster_encryption_policy_name, "${local.iam_role_name}-ClusterEncryption")
# Standard EKS cluster
eks_standard_iam_role_policies = { for k, v in {
AmazonEKSClusterPolicy = "${local.iam_role_policy_prefix}/AmazonEKSClusterPolicy",
} : k => v if !local.create_outposts_local_cluster && !local.auto_mode_enabled }
# EKS cluster with EKS auto mode enabled
eks_auto_mode_iam_role_policies = { for k, v in {
AmazonEKSClusterPolicy = "${local.iam_role_policy_prefix}/AmazonEKSClusterPolicy"
AmazonEKSComputePolicy = "${local.iam_role_policy_prefix}/AmazonEKSComputePolicy"
AmazonEKSBlockStoragePolicy = "${local.iam_role_policy_prefix}/AmazonEKSBlockStoragePolicy"
AmazonEKSLoadBalancingPolicy = "${local.iam_role_policy_prefix}/AmazonEKSLoadBalancingPolicy"
AmazonEKSNetworkingPolicy = "${local.iam_role_policy_prefix}/AmazonEKSNetworkingPolicy"
} : k => v if !local.create_outposts_local_cluster && local.auto_mode_enabled }
# EKS local cluster on Outposts
eks_outpost_iam_role_policies = { for k, v in {
AmazonEKSClusterPolicy = "${local.iam_role_policy_prefix}/AmazonEKSLocalOutpostClusterPolicy"
} : k => v if local.create_outposts_local_cluster && !local.auto_mode_enabled }
# Security groups for pods
eks_sgpp_iam_role_policies = { for k, v in {
AmazonEKSVPCResourceController = "${local.iam_role_policy_prefix}/AmazonEKSVPCResourceController"
} : k => v if var.enable_security_groups_for_pods && !local.create_outposts_local_cluster && !local.auto_mode_enabled }
}
data "aws_iam_policy_document" "assume_role_policy" {
count = local.create && var.create_iam_role ? 1 : 0
statement {
sid = "EKSClusterAssumeRole"
actions = ["sts:AssumeRole"]
sid = "EKSClusterAssumeRole"
actions = [
"sts:AssumeRole",
"sts:TagSession",
]
principals {
type = "Service"
@@ -398,10 +479,8 @@ data "aws_iam_policy_document" "assume_role_policy" {
for_each = local.create_outposts_local_cluster ? [1] : []
content {
type = "Service"
identifiers = [
"ec2.amazonaws.com",
]
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
@@ -424,10 +503,12 @@ resource "aws_iam_role" "this" {
# Policies attached ref https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html
resource "aws_iam_role_policy_attachment" "this" {
for_each = { for k, v in {
AmazonEKSClusterPolicy = local.create_outposts_local_cluster ? "${local.iam_role_policy_prefix}/AmazonEKSLocalOutpostClusterPolicy" : "${local.iam_role_policy_prefix}/AmazonEKSClusterPolicy",
AmazonEKSVPCResourceController = "${local.iam_role_policy_prefix}/AmazonEKSVPCResourceController",
} : k => v if local.create_iam_role }
for_each = { for k, v in merge(
local.eks_standard_iam_role_policies,
local.eks_auto_mode_iam_role_policies,
local.eks_outpost_iam_role_policies,
local.eks_sgpp_iam_role_policies,
) : k => v if local.create_iam_role }
policy_arn = each.value
role = aws_iam_role.this[0].name
@@ -602,3 +683,218 @@ resource "aws_eks_identity_provider_config" "this" {
tags = merge(var.tags, try(each.value.tags, {}))
}
################################################################################
# EKS Auto Node IAM Role
################################################################################
locals {
create_node_iam_role = local.create && var.create_node_iam_role && local.auto_mode_nodepools_enabled
node_iam_role_name = coalesce(var.node_iam_role_name, "${var.cluster_name}-eks-auto")
create_node_iam_role_custom_policy = local.create_node_iam_role && (var.enable_node_custom_tags_permissions || length(var.node_iam_role_policy_statements) > 0)
}
data "aws_iam_policy_document" "node_assume_role_policy" {
count = local.create_node_iam_role ? 1 : 0
statement {
sid = "EKSAutoNodeAssumeRole"
actions = [
"sts:AssumeRole",
"sts:TagSession",
]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "eks_auto" {
count = local.create_node_iam_role ? 1 : 0
name = var.node_iam_role_use_name_prefix ? null : local.node_iam_role_name
name_prefix = var.node_iam_role_use_name_prefix ? "${local.node_iam_role_name}-" : null
path = var.node_iam_role_path
description = var.node_iam_role_description
assume_role_policy = data.aws_iam_policy_document.node_assume_role_policy[0].json
permissions_boundary = var.node_iam_role_permissions_boundary
force_detach_policies = true
tags = merge(var.tags, var.node_iam_role_tags)
}
# Policies attached ref https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html
resource "aws_iam_role_policy_attachment" "eks_auto" {
for_each = { for k, v in {
AmazonEKSWorkerNodeMinimalPolicy = "${local.iam_role_policy_prefix}/AmazonEKSWorkerNodeMinimalPolicy",
AmazonEC2ContainerRegistryPullOnly = "${local.iam_role_policy_prefix}/AmazonEC2ContainerRegistryPullOnly",
} : k => v if local.create_node_iam_role }
policy_arn = each.value
role = aws_iam_role.eks_auto[0].name
}
resource "aws_iam_role_policy_attachment" "eks_auto_additional" {
for_each = { for k, v in var.node_iam_role_additional_policies : k => v if local.create_node_iam_role }
policy_arn = each.value
role = aws_iam_role.eks_auto[0].name
}
resource "aws_iam_role_policy_attachment" "eks_auto_custom" {
count = local.create_node_iam_role_custom_policy ? 1 : 0
policy_arn = aws_iam_policy.eks_auto_custom[0].arn
role = aws_iam_role.eks_auto[0].name
}
data "aws_iam_policy_document" "eks_auto_custom" {
count = local.create_node_iam_role_custom_policy ? 1 : 0
dynamic "statement" {
for_each = var.enable_node_custom_tags_permissions ? [1] : []
content {
sid = "Compute"
actions = [
"ec2:CreateFleet",
"ec2:RunInstances",
"ec2:CreateLaunchTemplate",
]
resources = ["*"]
condition {
test = "StringEquals"
variable = "aws:RequestTag/eks:eks-cluster-name"
values = ["$${aws:PrincipalTag/eks:eks-cluster-name}"]
}
condition {
test = "StringLike"
variable = "aws:RequestTag/eks:kubernetes-node-class-name"
values = ["*"]
}
condition {
test = "StringLike"
variable = "aws:RequestTag/eks:kubernetes-node-pool-name"
values = ["*"]
}
}
}
dynamic "statement" {
for_each = var.enable_node_custom_tags_permissions ? [1] : []
content {
sid = "Storage"
actions = [
"ec2:CreateVolume",
"ec2:CreateSnapshot",
]
resources = [
"arn:${local.partition}:ec2:*:*:volume/*",
"arn:${local.partition}:ec2:*:*:snapshot/*",
]
condition {
test = "StringEquals"
variable = "aws:RequestTag/eks:eks-cluster-name"
values = ["$${aws:PrincipalTag/eks:eks-cluster-name}"]
}
}
}
dynamic "statement" {
for_each = var.enable_node_custom_tags_permissions ? [1] : []
content {
sid = "Networking"
actions = ["ec2:CreateNetworkInterface"]
resources = ["*"]
condition {
test = "StringEquals"
variable = "aws:RequestTag/eks:eks-cluster-name"
values = ["$${aws:PrincipalTag/eks:eks-cluster-name}"]
}
condition {
test = "StringEquals"
variable = "aws:RequestTag/eks:kubernetes-cni-node-name"
values = ["*"]
}
}
}
dynamic "statement" {
for_each = var.enable_node_custom_tags_permissions ? [1] : []
content {
sid = "LoadBalancer"
actions = [
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:CreateRule",
"ec2:CreateSecurityGroup",
]
resources = ["*"]
condition {
test = "StringEquals"
variable = "aws:RequestTag/eks:eks-cluster-name"
values = ["$${aws:PrincipalTag/eks:eks-cluster-name}"]
}
}
}
dynamic "statement" {
for_each = var.enable_node_custom_tags_permissions ? [1] : []
content {
sid = "ShieldProtection"
actions = ["shield:CreateProtection"]
resources = ["*"]
condition {
test = "StringEquals"
variable = "aws:RequestTag/eks:eks-cluster-name"
values = ["$${aws:PrincipalTag/eks:eks-cluster-name}"]
}
}
}
dynamic "statement" {
for_each = var.enable_node_custom_tags_permissions ? [1] : []
content {
sid = "ShieldTagResource"
actions = ["shield:TagResource"]
resources = ["arn:${local.partition}:shield::*:protection/*"]
condition {
test = "StringEquals"
variable = "aws:RequestTag/eks:eks-cluster-name"
values = ["$${aws:PrincipalTag/eks:eks-cluster-name}"]
}
}
}
}
resource "aws_iam_policy" "eks_auto_custom" {
count = local.create_node_iam_role_custom_policy ? 1 : 0
name = var.node_iam_role_use_name_prefix ? null : local.node_iam_role_name
name_prefix = var.node_iam_role_use_name_prefix ? "${local.node_iam_role_name}-" : null
path = var.node_iam_role_path
description = var.node_iam_role_description
policy = data.aws_iam_policy_document.eks_auto_custom[0].json
tags = merge(var.tags, var.node_iam_role_tags)
}

View File

@@ -64,13 +64,13 @@ module "eks_managed_node_group" {
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -29,13 +29,13 @@ module "fargate_profile" {
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -0,0 +1,159 @@
# EKS Hybrid Node Role Module
Terraform module which creates IAM role and policy resources for Amazon EKS Hybrid Node(s).
## Usage
EKS Hybrid nodes use the AWS IAM Authenticator and temporary IAM credentials provisioned by AWS SSM or AWS IAM Roles Anywhere to authenticate with the EKS cluster. This module supports both SSM and IAM Roles Anywhere based IAM permissions.
### SSM
```hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
...
access_entries = {
hybrid-node-role = {
principal_arn = module.eks_hybrid_node_role.arn
type = "HYBRID_LINUX"
}
}
}
module "eks_hybrid_node_role" {
source = "terraform-aws-modules/eks/aws//modules/hybrid-node-role"
name = "hybrid"
tags = {
Environment = "dev"
Terraform = "true"
}
}
```
### IAM Roles Anywhere
```hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
...
access_entries = {
hybrid-node-role = {
principal_arn = module.eks_hybrid_node_role.arn
type = "HYBRID_LINUX"
}
}
}
module "eks_hybrid_node_role" {
source = "terraform-aws-modules/eks/aws//modules/hybrid-node-role"
name = "hybrid-ira"
enable_ira = true
ira_trust_anchor_source_type = "CERTIFICATE_BUNDLE"
ira_trust_anchor_x509_certificate_data = <<-EOT
MIIFMzCCAxugAwIBAgIRAMnVXU7ncv/+Cl16eJbZ9hswDQYJKoZIhvcNAQELBQAw
...
MGx/BMRkrNUVcg3xA0lhECo/olodCkmZo5/mjybbjFQwJzDSKFoW
EOT
tags = {
Environment = "dev"
Terraform = "true"
}
}
```
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [aws_iam_policy.intermediate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
| [aws_iam_role.intermediate](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_attachment.intermediate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_rolesanywhere_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rolesanywhere_profile) | resource |
| [aws_rolesanywhere_trust_anchor.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rolesanywhere_trust_anchor) | resource |
| [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.intermediate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.intermediate_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_cluster_arns"></a> [cluster\_arns](#input\_cluster\_arns) | List of EKS cluster ARNs to allow the node to describe | `list(string)` | <pre>[<br/> "*"<br/>]</pre> | no |
| <a name="input_create"></a> [create](#input\_create) | Controls if resources should be created (affects nearly all resources) | `bool` | `true` | no |
| <a name="input_description"></a> [description](#input\_description) | IAM role description | `string` | `"EKS Hybrid Node IAM role"` | no |
| <a name="input_enable_ira"></a> [enable\_ira](#input\_enable\_ira) | Enables IAM Roles Anywhere based IAM permissions on the node | `bool` | `false` | no |
| <a name="input_enable_pod_identity"></a> [enable\_pod\_identity](#input\_enable\_pod\_identity) | Enables EKS Pod Identity based IAM permissions on the node | `bool` | `true` | no |
| <a name="input_intermediate_policy_name"></a> [intermediate\_policy\_name](#input\_intermediate\_policy\_name) | Name of the IAM policy | `string` | `null` | no |
| <a name="input_intermediate_policy_statements"></a> [intermediate\_policy\_statements](#input\_intermediate\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no |
| <a name="input_intermediate_policy_use_name_prefix"></a> [intermediate\_policy\_use\_name\_prefix](#input\_intermediate\_policy\_use\_name\_prefix) | Determines whether the name of the IAM policy (`intermediate_policy_name`) is used as a prefix | `bool` | `true` | no |
| <a name="input_intermediate_role_description"></a> [intermediate\_role\_description](#input\_intermediate\_role\_description) | IAM role description | `string` | `"EKS Hybrid Node IAM Roles Anywhere intermediate IAM role"` | no |
| <a name="input_intermediate_role_name"></a> [intermediate\_role\_name](#input\_intermediate\_role\_name) | Name of the IAM role | `string` | `null` | no |
| <a name="input_intermediate_role_path"></a> [intermediate\_role\_path](#input\_intermediate\_role\_path) | Path of the IAM role | `string` | `"/"` | no |
| <a name="input_intermediate_role_policies"></a> [intermediate\_role\_policies](#input\_intermediate\_role\_policies) | Policies to attach to the IAM role in `{'static_name' = 'policy_arn'}` format | `map(string)` | `{}` | no |
| <a name="input_intermediate_role_use_name_prefix"></a> [intermediate\_role\_use\_name\_prefix](#input\_intermediate\_role\_use\_name\_prefix) | Determines whether the name of the IAM role (`intermediate_role_name`) is used as a prefix | `bool` | `true` | no |
| <a name="input_ira_profile_duration_seconds"></a> [ira\_profile\_duration\_seconds](#input\_ira\_profile\_duration\_seconds) | The number of seconds the vended session credentials are valid for. Defaults to `3600` | `number` | `null` | no |
| <a name="input_ira_profile_managed_policy_arns"></a> [ira\_profile\_managed\_policy\_arns](#input\_ira\_profile\_managed\_policy\_arns) | A list of managed policy ARNs that apply to the vended session credentials | `list(string)` | `[]` | no |
| <a name="input_ira_profile_name"></a> [ira\_profile\_name](#input\_ira\_profile\_name) | Name of the Roles Anywhere profile | `string` | `null` | no |
| <a name="input_ira_profile_require_instance_properties"></a> [ira\_profile\_require\_instance\_properties](#input\_ira\_profile\_require\_instance\_properties) | Specifies whether instance properties are required in [CreateSession](https://docs.aws.amazon.com/rolesanywhere/latest/APIReference/API_CreateSession.html) requests with this profile | `bool` | `null` | no |
| <a name="input_ira_profile_session_policy"></a> [ira\_profile\_session\_policy](#input\_ira\_profile\_session\_policy) | A session policy that applies to the trust boundary of the vended session credentials | `string` | `null` | no |
| <a name="input_ira_trust_anchor_acm_pca_arn"></a> [ira\_trust\_anchor\_acm\_pca\_arn](#input\_ira\_trust\_anchor\_acm\_pca\_arn) | The ARN of the ACM PCA that issued the trust anchor certificate | `string` | `null` | no |
| <a name="input_ira_trust_anchor_name"></a> [ira\_trust\_anchor\_name](#input\_ira\_trust\_anchor\_name) | Name of the Roles Anywhere trust anchor | `string` | `null` | no |
| <a name="input_ira_trust_anchor_notification_settings"></a> [ira\_trust\_anchor\_notification\_settings](#input\_ira\_trust\_anchor\_notification\_settings) | Notification settings for the trust anchor | `any` | `[]` | no |
| <a name="input_ira_trust_anchor_source_type"></a> [ira\_trust\_anchor\_source\_type](#input\_ira\_trust\_anchor\_source\_type) | The source type of the trust anchor | `string` | `null` | no |
| <a name="input_ira_trust_anchor_x509_certificate_data"></a> [ira\_trust\_anchor\_x509\_certificate\_data](#input\_ira\_trust\_anchor\_x509\_certificate\_data) | The X.509 certificate data of the trust anchor | `string` | `null` | no |
| <a name="input_max_session_duration"></a> [max\_session\_duration](#input\_max\_session\_duration) | Maximum API session duration in seconds between 3600 and 43200 | `number` | `null` | no |
| <a name="input_name"></a> [name](#input\_name) | Name of the IAM role | `string` | `"EKSHybridNode"` | no |
| <a name="input_path"></a> [path](#input\_path) | Path of the IAM role | `string` | `"/"` | no |
| <a name="input_permissions_boundary_arn"></a> [permissions\_boundary\_arn](#input\_permissions\_boundary\_arn) | Permissions boundary ARN to use for the IAM role | `string` | `null` | no |
| <a name="input_policies"></a> [policies](#input\_policies) | Policies to attach to the IAM role in `{'static_name' = 'policy_arn'}` format | `map(string)` | `{}` | no |
| <a name="input_policy_description"></a> [policy\_description](#input\_policy\_description) | IAM policy description | `string` | `"EKS Hybrid Node IAM role policy"` | no |
| <a name="input_policy_name"></a> [policy\_name](#input\_policy\_name) | Name of the IAM policy | `string` | `"EKSHybridNode"` | no |
| <a name="input_policy_path"></a> [policy\_path](#input\_policy\_path) | Path of the IAM policy | `string` | `"/"` | no |
| <a name="input_policy_statements"></a> [policy\_statements](#input\_policy\_statements) | A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed | `any` | `[]` | no |
| <a name="input_policy_use_name_prefix"></a> [policy\_use\_name\_prefix](#input\_policy\_use\_name\_prefix) | Determines whether the name of the IAM policy (`policy_name`) is used as a prefix | `bool` | `true` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | A map of additional tags to add the the IAM role | `map(any)` | `{}` | no |
| <a name="input_trust_anchor_arns"></a> [trust\_anchor\_arns](#input\_trust\_anchor\_arns) | List of IAM Roles Anywhere trust anchor ARNs. Required if `enable_ira` is set to `true` | `list(string)` | `[]` | no |
| <a name="input_use_name_prefix"></a> [use\_name\_prefix](#input\_use\_name\_prefix) | Determines whether the name of the IAM role (`name`) is used as a prefix | `bool` | `true` | no |
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_arn"></a> [arn](#output\_arn) | The Amazon Resource Name (ARN) specifying the node IAM role |
| <a name="output_intermediate_role_arn"></a> [intermediate\_role\_arn](#output\_intermediate\_role\_arn) | The Amazon Resource Name (ARN) specifying the node IAM role |
| <a name="output_intermediate_role_name"></a> [intermediate\_role\_name](#output\_intermediate\_role\_name) | The name of the node IAM role |
| <a name="output_intermediate_role_unique_id"></a> [intermediate\_role\_unique\_id](#output\_intermediate\_role\_unique\_id) | Stable and unique string identifying the node IAM role |
| <a name="output_name"></a> [name](#output\_name) | The name of the node IAM role |
| <a name="output_unique_id"></a> [unique\_id](#output\_unique\_id) | Stable and unique string identifying the node IAM role |
<!-- END_TF_DOCS -->

View File

@@ -0,0 +1,369 @@
data "aws_partition" "current" {
count = var.create ? 1 : 0
}
locals {
partition = try(data.aws_partition.current[0].partition, "aws")
}
################################################################################
# Node IAM Role
################################################################################
data "aws_iam_policy_document" "assume_role" {
count = var.create ? 1 : 0
# SSM
dynamic "statement" {
for_each = var.enable_ira ? [] : [1]
content {
actions = [
"sts:AssumeRole",
"sts:TagSession",
]
principals {
type = "Service"
identifiers = ["ssm.amazonaws.com"]
}
}
}
# IAM Roles Anywhere
dynamic "statement" {
for_each = var.enable_ira ? [1] : []
content {
actions = [
"sts:TagSession",
"sts:SetSourceIdentity",
]
principals {
type = "AWS"
identifiers = [aws_iam_role.intermediate[0].arn]
}
}
}
dynamic "statement" {
for_each = var.enable_ira ? [1] : []
content {
actions = [
"sts:AssumeRole",
"sts:TagSession",
]
principals {
type = "AWS"
identifiers = [aws_iam_role.intermediate[0].arn]
}
condition {
test = "StringEquals"
variable = "sts:RoleSessionName"
values = ["$${aws:PrincipalTag/x509Subject/CN}"]
}
}
}
}
resource "aws_iam_role" "this" {
count = var.create ? 1 : 0
name = var.use_name_prefix ? null : var.name
name_prefix = var.use_name_prefix ? "${var.name}-" : null
path = var.path
description = var.description
assume_role_policy = data.aws_iam_policy_document.assume_role[0].json
max_session_duration = var.max_session_duration
permissions_boundary = var.permissions_boundary_arn
force_detach_policies = true
tags = var.tags
}
################################################################################
# Node IAM Role Policy
################################################################################
data "aws_iam_policy_document" "this" {
count = var.create ? 1 : 0
statement {
actions = [
"ssm:DeregisterManagedInstance",
"ssm:DescribeInstanceInformation",
]
resources = ["*"]
}
statement {
actions = ["eks:DescribeCluster"]
resources = var.cluster_arns
}
dynamic "statement" {
for_each = var.enable_pod_identity ? [1] : []
content {
actions = ["eks-auth:AssumeRoleForPodIdentity"]
resources = ["*"]
}
}
dynamic "statement" {
for_each = var.policy_statements
content {
sid = try(statement.value.sid, null)
actions = try(statement.value.actions, null)
not_actions = try(statement.value.not_actions, null)
effect = try(statement.value.effect, null)
resources = try(statement.value.resources, null)
not_resources = try(statement.value.not_resources, null)
dynamic "principals" {
for_each = try(statement.value.principals, [])
content {
type = principals.value.type
identifiers = principals.value.identifiers
}
}
dynamic "not_principals" {
for_each = try(statement.value.not_principals, [])
content {
type = not_principals.value.type
identifiers = not_principals.value.identifiers
}
}
dynamic "condition" {
for_each = try(statement.value.conditions, [])
content {
test = condition.value.test
values = condition.value.values
variable = condition.value.variable
}
}
}
}
}
resource "aws_iam_policy" "this" {
count = var.create ? 1 : 0
name = var.policy_use_name_prefix ? null : var.policy_name
name_prefix = var.policy_use_name_prefix ? "${var.policy_name}-" : null
path = var.policy_path
description = var.policy_description
policy = data.aws_iam_policy_document.this[0].json
tags = var.tags
}
resource "aws_iam_role_policy_attachment" "this" {
for_each = { for k, v in merge(
{
node = try(aws_iam_policy.this[0].arn, null)
AmazonSSMManagedInstanceCore = "arn:${local.partition}:iam::aws:policy/AmazonSSMManagedInstanceCore"
AmazonEC2ContainerRegistryPullOnly = "arn:${local.partition}:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly"
},
var.policies
) : k => v if var.create }
policy_arn = each.value
role = aws_iam_role.this[0].name
}
################################################################################
# Roles Anywhere Profile
################################################################################
locals {
enable_ira = var.create && var.enable_ira
}
resource "aws_rolesanywhere_profile" "this" {
count = local.enable_ira ? 1 : 0
duration_seconds = var.ira_profile_duration_seconds
managed_policy_arns = var.ira_profile_managed_policy_arns
name = try(coalesce(var.ira_profile_name, var.name), null)
require_instance_properties = var.ira_profile_require_instance_properties
role_arns = [aws_iam_role.intermediate[0].arn]
session_policy = var.ira_profile_session_policy
tags = var.tags
}
################################################################################
# Roles Anywhere Trust Anchor
################################################################################
resource "aws_rolesanywhere_trust_anchor" "this" {
count = local.enable_ira ? 1 : 0
name = try(coalesce(var.ira_trust_anchor_name, var.name), null)
dynamic "notification_settings" {
for_each = var.ira_trust_anchor_notification_settings
content {
channel = try(notification_settings.value.channel, null)
enabled = try(notification_settings.value.enabled, null)
event = try(notification_settings.value.event, null)
threshold = try(notification_settings.value.threshold, null)
}
}
source {
source_data {
acm_pca_arn = var.ira_trust_anchor_acm_pca_arn
x509_certificate_data = var.ira_trust_anchor_x509_certificate_data
}
source_type = var.ira_trust_anchor_source_type
}
tags = var.tags
}
################################################################################
# Intermediate IAM Role
################################################################################
data "aws_iam_policy_document" "intermediate_assume_role" {
count = local.enable_ira ? 1 : 0
statement {
actions = [
"sts:AssumeRole",
"sts:TagSession",
"sts:SetSourceIdentity",
]
principals {
type = "Service"
identifiers = ["rolesanywhere.amazonaws.com"]
}
condition {
test = "ArnEquals"
variable = "aws:SourceArn"
values = concat(var.trust_anchor_arns, aws_rolesanywhere_trust_anchor.this[*].arn)
}
}
}
locals {
intermediate_role_use_name_prefix = coalesce(var.intermediate_role_use_name_prefix, var.use_name_prefix)
intermediate_role_name = coalesce(var.intermediate_role_name, "${var.name}-inter")
}
resource "aws_iam_role" "intermediate" {
count = local.enable_ira ? 1 : 0
name = local.intermediate_role_use_name_prefix ? null : local.intermediate_role_name
name_prefix = local.intermediate_role_use_name_prefix ? "${local.intermediate_role_name}-" : null
path = coalesce(var.intermediate_role_path, var.path)
description = var.intermediate_role_description
assume_role_policy = data.aws_iam_policy_document.intermediate_assume_role[0].json
max_session_duration = var.max_session_duration
permissions_boundary = var.permissions_boundary_arn
force_detach_policies = true
tags = var.tags
}
################################################################################
# Intermediate IAM Role Policy
################################################################################
data "aws_iam_policy_document" "intermediate" {
count = local.enable_ira ? 1 : 0
statement {
actions = ["eks:DescribeCluster"]
resources = var.cluster_arns
}
dynamic "statement" {
for_each = var.intermediate_policy_statements
content {
sid = try(statement.value.sid, null)
actions = try(statement.value.actions, null)
not_actions = try(statement.value.not_actions, null)
effect = try(statement.value.effect, null)
resources = try(statement.value.resources, null)
not_resources = try(statement.value.not_resources, null)
dynamic "principals" {
for_each = try(statement.value.principals, [])
content {
type = principals.value.type
identifiers = principals.value.identifiers
}
}
dynamic "not_principals" {
for_each = try(statement.value.not_principals, [])
content {
type = not_principals.value.type
identifiers = not_principals.value.identifiers
}
}
dynamic "condition" {
for_each = try(statement.value.conditions, [])
content {
test = condition.value.test
values = condition.value.values
variable = condition.value.variable
}
}
}
}
}
locals {
intermediate_policy_use_name_prefix = coalesce(var.intermediate_policy_use_name_prefix, var.policy_use_name_prefix)
intermediate_policy_name = coalesce(var.intermediate_policy_name, var.policy_name)
}
resource "aws_iam_policy" "intermediate" {
count = local.enable_ira ? 1 : 0
name = local.intermediate_policy_use_name_prefix ? null : local.intermediate_policy_name
name_prefix = local.intermediate_policy_use_name_prefix ? "${local.intermediate_policy_name}-" : null
path = var.policy_path
description = var.policy_description
policy = data.aws_iam_policy_document.intermediate[0].json
tags = var.tags
}
resource "aws_iam_role_policy_attachment" "intermediate" {
for_each = { for k, v in merge(
{
intermediate = try(aws_iam_policy.intermediate[0].arn, null)
AmazonEC2ContainerRegistryPullOnly = "arn:${local.partition}:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly"
},
var.intermediate_role_policies
) : k => v if local.enable_ira }
policy_arn = each.value
role = aws_iam_role.this[0].name
}

View File

@@ -0,0 +1,37 @@
################################################################################
# Node IAM Role
################################################################################
output "name" {
description = "The name of the node IAM role"
value = try(aws_iam_role.this[0].name, null)
}
output "arn" {
description = "The Amazon Resource Name (ARN) specifying the node IAM role"
value = try(aws_iam_role.this[0].arn, null)
}
output "unique_id" {
description = "Stable and unique string identifying the node IAM role"
value = try(aws_iam_role.this[0].unique_id, null)
}
################################################################################
# Intermedaite IAM Role
################################################################################
output "intermediate_role_name" {
description = "The name of the node IAM role"
value = try(aws_iam_role.intermediate[0].name, null)
}
output "intermediate_role_arn" {
description = "The Amazon Resource Name (ARN) specifying the node IAM role"
value = try(aws_iam_role.intermediate[0].arn, null)
}
output "intermediate_role_unique_id" {
description = "Stable and unique string identifying the node IAM role"
value = try(aws_iam_role.intermediate[0].unique_id, null)
}

View File

@@ -0,0 +1,239 @@
variable "create" {
description = "Controls if resources should be created (affects nearly all resources)"
type = bool
default = true
}
################################################################################
# Node IAM Role
################################################################################
variable "name" {
description = "Name of the IAM role"
type = string
default = "EKSHybridNode"
}
variable "use_name_prefix" {
description = "Determines whether the name of the IAM role (`name`) is used as a prefix"
type = bool
default = true
}
variable "path" {
description = "Path of the IAM role"
type = string
default = "/"
}
variable "description" {
description = "IAM role description"
type = string
default = "EKS Hybrid Node IAM role"
}
variable "max_session_duration" {
description = "Maximum API session duration in seconds between 3600 and 43200"
type = number
default = null
}
variable "permissions_boundary_arn" {
description = "Permissions boundary ARN to use for the IAM role"
type = string
default = null
}
variable "tags" {
description = "A map of additional tags to add the the IAM role"
type = map(any)
default = {}
}
variable "enable_ira" {
description = "Enables IAM Roles Anywhere based IAM permissions on the node"
type = bool
default = false
}
variable "trust_anchor_arns" {
description = "List of IAM Roles Anywhere trust anchor ARNs. Required if `enable_ira` is set to `true`"
type = list(string)
default = []
}
################################################################################
# Node IAM Role Policy
################################################################################
variable "policy_name" {
description = "Name of the IAM policy"
type = string
default = "EKSHybridNode"
}
variable "policy_use_name_prefix" {
description = "Determines whether the name of the IAM policy (`policy_name`) is used as a prefix"
type = bool
default = true
}
variable "policy_path" {
description = "Path of the IAM policy"
type = string
default = "/"
}
variable "policy_description" {
description = "IAM policy description"
type = string
default = "EKS Hybrid Node IAM role policy"
}
variable "policy_statements" {
description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed"
type = any
default = []
}
variable "policies" {
description = "Policies to attach to the IAM role in `{'static_name' = 'policy_arn'}` format"
type = map(string)
default = {}
}
variable "cluster_arns" {
description = "List of EKS cluster ARNs to allow the node to describe"
type = list(string)
default = ["*"]
}
variable "enable_pod_identity" {
description = "Enables EKS Pod Identity based IAM permissions on the node"
type = bool
default = true
}
################################################################################
# IAM Roles Anywhere Profile
################################################################################
variable "ira_profile_name" {
description = "Name of the Roles Anywhere profile"
type = string
default = null
}
variable "ira_profile_duration_seconds" {
description = "The number of seconds the vended session credentials are valid for. Defaults to `3600`"
type = number
default = null
}
variable "ira_profile_managed_policy_arns" {
description = "A list of managed policy ARNs that apply to the vended session credentials"
type = list(string)
default = []
}
variable "ira_profile_require_instance_properties" {
description = "Specifies whether instance properties are required in [CreateSession](https://docs.aws.amazon.com/rolesanywhere/latest/APIReference/API_CreateSession.html) requests with this profile"
type = bool
default = null
}
variable "ira_profile_session_policy" {
description = "A session policy that applies to the trust boundary of the vended session credentials"
type = string
default = null
}
################################################################################
# Roles Anywhere Trust Anchor
################################################################################
variable "ira_trust_anchor_name" {
description = "Name of the Roles Anywhere trust anchor"
type = string
default = null
}
variable "ira_trust_anchor_notification_settings" {
description = "Notification settings for the trust anchor"
type = any
default = []
}
variable "ira_trust_anchor_acm_pca_arn" {
description = "The ARN of the ACM PCA that issued the trust anchor certificate"
type = string
default = null
}
variable "ira_trust_anchor_x509_certificate_data" {
description = "The X.509 certificate data of the trust anchor"
type = string
default = null
}
variable "ira_trust_anchor_source_type" {
description = "The source type of the trust anchor"
type = string
default = null
}
################################################################################
# Intermediate IAM Role
################################################################################
variable "intermediate_role_name" {
description = "Name of the IAM role"
type = string
default = null
}
variable "intermediate_role_use_name_prefix" {
description = "Determines whether the name of the IAM role (`intermediate_role_name`) is used as a prefix"
type = bool
default = true
}
variable "intermediate_role_path" {
description = "Path of the IAM role"
type = string
default = "/"
}
variable "intermediate_role_description" {
description = "IAM role description"
type = string
default = "EKS Hybrid Node IAM Roles Anywhere intermediate IAM role"
}
################################################################################
# Intermediate IAM Role Policy
################################################################################
variable "intermediate_policy_name" {
description = "Name of the IAM policy"
type = string
default = null
}
variable "intermediate_policy_use_name_prefix" {
description = "Determines whether the name of the IAM policy (`intermediate_policy_name`) is used as a prefix"
type = bool
default = true
}
variable "intermediate_policy_statements" {
description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed"
type = any
default = []
}
variable "intermediate_role_policies" {
description = "Policies to attach to the IAM role in `{'static_name' = 'policy_arn'}` format"
type = map(string)
default = {}
}

View File

@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.3.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.79"
}
}
}

View File

@@ -86,13 +86,13 @@ module "karpenter" {
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -43,13 +43,13 @@ module "self_managed_node_group" {
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -176,12 +176,12 @@ output "cluster_tls_certificate_sha1_fingerprint" {
################################################################################
output "cluster_iam_role_name" {
description = "IAM role name of the EKS cluster"
description = "Cluster IAM role name"
value = try(aws_iam_role.this[0].name, null)
}
output "cluster_iam_role_arn" {
description = "IAM role ARN of the EKS cluster"
description = "Cluster IAM role ARN"
value = try(aws_iam_role.this[0].arn, null)
}
@@ -190,6 +190,25 @@ output "cluster_iam_role_unique_id" {
value = try(aws_iam_role.this[0].unique_id, null)
}
################################################################################
# EKS Auto Node IAM Role
################################################################################
output "node_iam_role_name" {
description = "EKS Auto node IAM role name"
value = try(aws_iam_role.eks_auto[0].name, null)
}
output "node_iam_role_arn" {
description = "EKS Auto node IAM role ARN"
value = try(aws_iam_role.eks_auto[0].arn, null)
}
output "node_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = try(aws_iam_role.eks_auto[0].unique_id, null)
}
################################################################################
# EKS Addons
################################################################################

View File

@@ -1,4 +1,4 @@
# Fargate Profile
# EKS Fargate Profile
## Usage
@@ -18,13 +18,13 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules
@@ -58,8 +58,8 @@ No inputs.
| <a name="output_cluster_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster |
| <a name="output_cluster_dualstack_oidc_issuer_url"></a> [cluster\_dualstack\_oidc\_issuer\_url](#output\_cluster\_dualstack\_oidc\_issuer\_url) | Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider |
| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN of the EKS cluster |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | Cluster IAM role ARN |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | Cluster IAM role name |
| <a name="output_cluster_iam_role_unique_id"></a> [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_cluster_id"></a> [cluster\_id](#output\_cluster\_id) | The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts |
| <a name="output_cluster_identity_providers"></a> [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled |
@@ -79,6 +79,9 @@ No inputs.
| <a name="output_kms_key_arn"></a> [kms\_key\_arn](#output\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key |
| <a name="output_kms_key_id"></a> [kms\_key\_id](#output\_kms\_key\_id) | The globally unique identifier for the key |
| <a name="output_kms_key_policy"></a> [kms\_key\_policy](#output\_kms\_key\_policy) | The IAM resource policy set on the key |
| <a name="output_node_iam_role_arn"></a> [node\_iam\_role\_arn](#output\_node\_iam\_role\_arn) | EKS Auto node IAM role ARN |
| <a name="output_node_iam_role_name"></a> [node\_iam\_role\_name](#output\_node\_iam\_role\_name) | EKS Auto node IAM role name |
| <a name="output_node_iam_role_unique_id"></a> [node\_iam\_role\_unique\_id](#output\_node\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_node_security_group_arn"></a> [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group |
| <a name="output_node_security_group_id"></a> [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group |
| <a name="output_oidc_provider"></a> [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) |

View File

@@ -2,7 +2,13 @@ provider "aws" {
region = local.region
}
data "aws_availability_zones" "available" {}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
name = "ex-${basename(path.cwd)}"

View File

@@ -0,0 +1,245 @@
################################################################################
# Cluster
################################################################################
output "cluster_arn" {
description = "The Amazon Resource Name (ARN) of the cluster"
value = module.eks.cluster_arn
}
output "cluster_certificate_authority_data" {
description = "Base64 encoded certificate data required to communicate with the cluster"
value = module.eks.cluster_certificate_authority_data
}
output "cluster_endpoint" {
description = "Endpoint for your Kubernetes API server"
value = module.eks.cluster_endpoint
}
output "cluster_id" {
description = "The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts"
value = module.eks.cluster_id
}
output "cluster_name" {
description = "The name of the EKS cluster"
value = module.eks.cluster_name
}
output "cluster_oidc_issuer_url" {
description = "The URL on the EKS cluster for the OpenID Connect identity provider"
value = module.eks.cluster_oidc_issuer_url
}
output "cluster_dualstack_oidc_issuer_url" {
description = "Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider"
value = module.eks.cluster_dualstack_oidc_issuer_url
}
output "cluster_platform_version" {
description = "Platform version for the cluster"
value = module.eks.cluster_platform_version
}
output "cluster_status" {
description = "Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED`"
value = module.eks.cluster_status
}
output "cluster_primary_security_group_id" {
description = "Cluster security group that was created by Amazon EKS for the cluster. Managed node groups use this security group for control-plane-to-data-plane communication. Referred to as 'Cluster security group' in the EKS console"
value = module.eks.cluster_primary_security_group_id
}
output "cluster_service_cidr" {
description = "The CIDR block where Kubernetes pod and service IP addresses are assigned from"
value = module.eks.cluster_service_cidr
}
output "cluster_ip_family" {
description = "The IP family used by the cluster (e.g. `ipv4` or `ipv6`)"
value = module.eks.cluster_ip_family
}
################################################################################
# Access Entry
################################################################################
output "access_entries" {
description = "Map of access entries created and their attributes"
value = module.eks.access_entries
}
################################################################################
# KMS Key
################################################################################
output "kms_key_arn" {
description = "The Amazon Resource Name (ARN) of the key"
value = module.eks.kms_key_arn
}
output "kms_key_id" {
description = "The globally unique identifier for the key"
value = module.eks.kms_key_id
}
output "kms_key_policy" {
description = "The IAM resource policy set on the key"
value = module.eks.kms_key_policy
}
################################################################################
# Security Group
################################################################################
output "cluster_security_group_arn" {
description = "Amazon Resource Name (ARN) of the cluster security group"
value = module.eks.cluster_security_group_arn
}
output "cluster_security_group_id" {
description = "ID of the cluster security group"
value = module.eks.cluster_security_group_id
}
################################################################################
# Node Security Group
################################################################################
output "node_security_group_arn" {
description = "Amazon Resource Name (ARN) of the node shared security group"
value = module.eks.node_security_group_arn
}
output "node_security_group_id" {
description = "ID of the node shared security group"
value = module.eks.node_security_group_id
}
################################################################################
# IRSA
################################################################################
output "oidc_provider" {
description = "The OpenID Connect identity provider (issuer URL without leading `https://`)"
value = module.eks.oidc_provider
}
output "oidc_provider_arn" {
description = "The ARN of the OIDC Provider if `enable_irsa = true`"
value = module.eks.oidc_provider_arn
}
output "cluster_tls_certificate_sha1_fingerprint" {
description = "The SHA1 fingerprint of the public key of the cluster's certificate"
value = module.eks.cluster_tls_certificate_sha1_fingerprint
}
################################################################################
# IAM Role
################################################################################
output "cluster_iam_role_name" {
description = "Cluster IAM role name"
value = module.eks.cluster_iam_role_name
}
output "cluster_iam_role_arn" {
description = "Cluster IAM role ARN"
value = module.eks.cluster_iam_role_arn
}
output "cluster_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = module.eks.cluster_iam_role_unique_id
}
################################################################################
# EKS Auto Node IAM Role
################################################################################
output "node_iam_role_name" {
description = "EKS Auto node IAM role name"
value = module.eks.node_iam_role_name
}
output "node_iam_role_arn" {
description = "EKS Auto node IAM role ARN"
value = module.eks.node_iam_role_arn
}
output "node_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = module.eks.node_iam_role_unique_id
}
################################################################################
# EKS Addons
################################################################################
output "cluster_addons" {
description = "Map of attribute maps for all EKS cluster addons enabled"
value = module.eks.cluster_addons
}
################################################################################
# EKS Identity Provider
################################################################################
output "cluster_identity_providers" {
description = "Map of attribute maps for all EKS identity providers enabled"
value = module.eks.cluster_identity_providers
}
################################################################################
# CloudWatch Log Group
################################################################################
output "cloudwatch_log_group_name" {
description = "Name of cloudwatch log group created"
value = module.eks.cloudwatch_log_group_name
}
output "cloudwatch_log_group_arn" {
description = "Arn of cloudwatch log group created"
value = module.eks.cloudwatch_log_group_arn
}
################################################################################
# Fargate Profile
################################################################################
output "fargate_profiles" {
description = "Map of attribute maps for all EKS Fargate Profiles created"
value = module.eks.fargate_profiles
}
################################################################################
# EKS Managed Node Group
################################################################################
output "eks_managed_node_groups" {
description = "Map of attribute maps for all EKS managed node groups created"
value = module.eks.eks_managed_node_groups
}
output "eks_managed_node_groups_autoscaling_group_names" {
description = "List of the autoscaling group names created by EKS managed node groups"
value = module.eks.eks_managed_node_groups_autoscaling_group_names
}
################################################################################
# Self Managed Node Group
################################################################################
output "self_managed_node_groups" {
description = "Map of attribute maps for all self managed node groups created"
value = module.eks.self_managed_node_groups
}
output "self_managed_node_groups_autoscaling_group_names" {
description = "List of the autoscaling group names created by self-managed node groups"
value = module.eks.self_managed_node_groups_autoscaling_group_names
}

View File

View File

@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.3.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.79"
}
}
}

View File

@@ -0,0 +1,65 @@
# EKS Hybrid Node IAM Role
## Usage
To provision the provided configurations you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply --auto-approve
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.
<!-- BEGIN_TF_DOCS -->
## Requirements
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
| <a name="requirement_tls"></a> [tls](#requirement\_tls) | >= 4.0 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_tls"></a> [tls](#provider\_tls) | >= 4.0 |
## Modules
| Name | Source | Version |
|------|--------|---------|
| <a name="module_disabled_eks_hybrid_node_role"></a> [disabled\_eks\_hybrid\_node\_role](#module\_disabled\_eks\_hybrid\_node\_role) | ../../modules/hybrid-node-role | n/a |
| <a name="module_eks_hybrid_node_role"></a> [eks\_hybrid\_node\_role](#module\_eks\_hybrid\_node\_role) | ../../modules/hybrid-node-role | n/a |
| <a name="module_ira_eks_hybrid_node_role"></a> [ira\_eks\_hybrid\_node\_role](#module\_ira\_eks\_hybrid\_node\_role) | ../../modules/hybrid-node-role | n/a |
## Resources
| Name | Type |
|------|------|
| [tls_private_key.example](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource |
| [tls_self_signed_cert.example](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/self_signed_cert) | resource |
## Inputs
No inputs.
## Outputs
| Name | Description |
|------|-------------|
| <a name="output_arn"></a> [arn](#output\_arn) | The Amazon Resource Name (ARN) specifying the node IAM role |
| <a name="output_intermediate_role_arn"></a> [intermediate\_role\_arn](#output\_intermediate\_role\_arn) | The Amazon Resource Name (ARN) specifying the node IAM role |
| <a name="output_intermediate_role_name"></a> [intermediate\_role\_name](#output\_intermediate\_role\_name) | The name of the node IAM role |
| <a name="output_intermediate_role_unique_id"></a> [intermediate\_role\_unique\_id](#output\_intermediate\_role\_unique\_id) | Stable and unique string identifying the node IAM role |
| <a name="output_ira_arn"></a> [ira\_arn](#output\_ira\_arn) | The Amazon Resource Name (ARN) specifying the node IAM role |
| <a name="output_ira_intermediate_role_arn"></a> [ira\_intermediate\_role\_arn](#output\_ira\_intermediate\_role\_arn) | The Amazon Resource Name (ARN) specifying the node IAM role |
| <a name="output_ira_intermediate_role_name"></a> [ira\_intermediate\_role\_name](#output\_ira\_intermediate\_role\_name) | The name of the node IAM role |
| <a name="output_ira_intermediate_role_unique_id"></a> [ira\_intermediate\_role\_unique\_id](#output\_ira\_intermediate\_role\_unique\_id) | Stable and unique string identifying the node IAM role |
| <a name="output_ira_name"></a> [ira\_name](#output\_ira\_name) | The name of the node IAM role |
| <a name="output_ira_unique_id"></a> [ira\_unique\_id](#output\_ira\_unique\_id) | Stable and unique string identifying the node IAM role |
| <a name="output_name"></a> [name](#output\_name) | The name of the node IAM role |
| <a name="output_unique_id"></a> [unique\_id](#output\_unique\_id) | Stable and unique string identifying the node IAM role |
<!-- END_TF_DOCS -->

View File

@@ -0,0 +1,84 @@
provider "aws" {
region = local.region
}
locals {
name = "ex-${basename(path.cwd)}"
region = "us-west-2"
tags = {
Test = local.name
GithubRepo = "terraform-aws-eks"
GithubOrg = "terraform-aws-modules"
}
}
################################################################################
# Hybrid Node IAM Module
################################################################################
# Default (SSM)
module "eks_hybrid_node_role" {
source = "../../modules/hybrid-node-role"
policy_statements = [
{
actions = [
"s3:Get*",
"s3:List*",
]
resources = ["*"]
}
]
tags = local.tags
}
# IAM Roles Anywhere
module "ira_eks_hybrid_node_role" {
source = "../../modules/hybrid-node-role"
name = "${local.name}-ira"
enable_ira = true
ira_trust_anchor_source_type = "CERTIFICATE_BUNDLE"
ira_trust_anchor_x509_certificate_data = local.cert_data
tags = local.tags
}
module "disabled_eks_hybrid_node_role" {
source = "../../modules/hybrid-node-role"
create = false
}
################################################################################
# Supporting Resources
################################################################################
resource "tls_private_key" "example" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "tls_self_signed_cert" "example" {
private_key_pem = tls_private_key.example.private_key_pem
subject {
common_name = "Custom root"
organization = "ACME Examples, Inc"
}
validity_period_hours = 17544
is_ca_certificate = true
allowed_uses = [
"cert_signing",
]
}
locals {
cert_data = trimspace(replace(trimprefix(tls_self_signed_cert.example.cert_pem, "-----BEGIN CERTIFICATE-----"), "-----END CERTIFICATE-----", ""))
}

View File

@@ -0,0 +1,71 @@
################################################################################
# Default (SSM) - Node IAM Role
################################################################################
# Node IAM Role
output "name" {
description = "The name of the node IAM role"
value = module.eks_hybrid_node_role.name
}
output "arn" {
description = "The Amazon Resource Name (ARN) specifying the node IAM role"
value = module.eks_hybrid_node_role.arn
}
output "unique_id" {
description = "Stable and unique string identifying the node IAM role"
value = module.eks_hybrid_node_role.unique_id
}
# Intermedaite IAM Role
output "intermediate_role_name" {
description = "The name of the node IAM role"
value = module.eks_hybrid_node_role.intermediate_role_name
}
output "intermediate_role_arn" {
description = "The Amazon Resource Name (ARN) specifying the node IAM role"
value = module.eks_hybrid_node_role.intermediate_role_arn
}
output "intermediate_role_unique_id" {
description = "Stable and unique string identifying the node IAM role"
value = module.eks_hybrid_node_role.intermediate_role_unique_id
}
################################################################################
# IAM Roles Anywhere - Node IAM Role
################################################################################
# Node IAM Role
output "ira_name" {
description = "The name of the node IAM role"
value = module.ira_eks_hybrid_node_role.name
}
output "ira_arn" {
description = "The Amazon Resource Name (ARN) specifying the node IAM role"
value = module.ira_eks_hybrid_node_role.arn
}
output "ira_unique_id" {
description = "Stable and unique string identifying the node IAM role"
value = module.ira_eks_hybrid_node_role.unique_id
}
# Intermedaite IAM Role
output "ira_intermediate_role_name" {
description = "The name of the node IAM role"
value = module.ira_eks_hybrid_node_role.intermediate_role_name
}
output "ira_intermediate_role_arn" {
description = "The Amazon Resource Name (ARN) specifying the node IAM role"
value = module.ira_eks_hybrid_node_role.intermediate_role_arn
}
output "ira_intermediate_role_unique_id" {
description = "Stable and unique string identifying the node IAM role"
value = module.ira_eks_hybrid_node_role.intermediate_role_unique_id
}

View File

View File

@@ -0,0 +1,14 @@
terraform {
required_version = ">= 1.3.2"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.79"
}
tls = {
source = "hashicorp/tls"
version = ">= 4.0"
}
}
}

View File

@@ -18,13 +18,13 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules
@@ -68,8 +68,8 @@ No inputs.
| <a name="output_cluster_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster |
| <a name="output_cluster_dualstack_oidc_issuer_url"></a> [cluster\_dualstack\_oidc\_issuer\_url](#output\_cluster\_dualstack\_oidc\_issuer\_url) | Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider |
| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN of the EKS cluster |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | Cluster IAM role ARN |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | Cluster IAM role name |
| <a name="output_cluster_iam_role_unique_id"></a> [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_cluster_id"></a> [cluster\_id](#output\_cluster\_id) | The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts |
| <a name="output_cluster_identity_providers"></a> [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled |
@@ -89,6 +89,9 @@ No inputs.
| <a name="output_kms_key_arn"></a> [kms\_key\_arn](#output\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key |
| <a name="output_kms_key_id"></a> [kms\_key\_id](#output\_kms\_key\_id) | The globally unique identifier for the key |
| <a name="output_kms_key_policy"></a> [kms\_key\_policy](#output\_kms\_key\_policy) | The IAM resource policy set on the key |
| <a name="output_node_iam_role_arn"></a> [node\_iam\_role\_arn](#output\_node\_iam\_role\_arn) | EKS Auto node IAM role ARN |
| <a name="output_node_iam_role_name"></a> [node\_iam\_role\_name](#output\_node\_iam\_role\_name) | EKS Auto node IAM role name |
| <a name="output_node_iam_role_unique_id"></a> [node\_iam\_role\_unique\_id](#output\_node\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_node_security_group_arn"></a> [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group |
| <a name="output_node_security_group_id"></a> [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group |
| <a name="output_oidc_provider"></a> [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) |

View File

@@ -3,7 +3,14 @@ provider "aws" {
}
data "aws_caller_identity" "current" {}
data "aws_availability_zones" "available" {}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
name = "ex-${replace(basename(path.cwd), "_", "-")}"

View File

@@ -142,12 +142,12 @@ output "cluster_tls_certificate_sha1_fingerprint" {
################################################################################
output "cluster_iam_role_name" {
description = "IAM role name of the EKS cluster"
description = "Cluster IAM role name"
value = module.eks.cluster_iam_role_name
}
output "cluster_iam_role_arn" {
description = "IAM role ARN of the EKS cluster"
description = "Cluster IAM role ARN"
value = module.eks.cluster_iam_role_arn
}
@@ -156,6 +156,25 @@ output "cluster_iam_role_unique_id" {
value = module.eks.cluster_iam_role_unique_id
}
################################################################################
# EKS Auto Node IAM Role
################################################################################
output "node_iam_role_name" {
description = "EKS Auto node IAM role name"
value = module.eks.node_iam_role_name
}
output "node_iam_role_arn" {
description = "EKS Auto node IAM role ARN"
value = module.eks.node_iam_role_arn
}
output "node_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = module.eks.node_iam_role_unique_id
}
################################################################################
# EKS Addons
################################################################################

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -22,13 +22,13 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -18,13 +18,13 @@ Note that this example may create resources which cost money. Run `terraform des
| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.3.2 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.75 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.79 |
## Providers
| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.75 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.79 |
## Modules
@@ -64,8 +64,8 @@ No inputs.
| <a name="output_cluster_certificate_authority_data"></a> [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster |
| <a name="output_cluster_dualstack_oidc_issuer_url"></a> [cluster\_dualstack\_oidc\_issuer\_url](#output\_cluster\_dualstack\_oidc\_issuer\_url) | Dual-stack compatible URL on the EKS cluster for the OpenID Connect identity provider |
| <a name="output_cluster_endpoint"></a> [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | IAM role ARN of the EKS cluster |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster |
| <a name="output_cluster_iam_role_arn"></a> [cluster\_iam\_role\_arn](#output\_cluster\_iam\_role\_arn) | Cluster IAM role ARN |
| <a name="output_cluster_iam_role_name"></a> [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | Cluster IAM role name |
| <a name="output_cluster_iam_role_unique_id"></a> [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_cluster_id"></a> [cluster\_id](#output\_cluster\_id) | The ID of the EKS cluster. Note: currently a value is returned only for local EKS clusters created on Outposts |
| <a name="output_cluster_identity_providers"></a> [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled |
@@ -85,6 +85,9 @@ No inputs.
| <a name="output_kms_key_arn"></a> [kms\_key\_arn](#output\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key |
| <a name="output_kms_key_id"></a> [kms\_key\_id](#output\_kms\_key\_id) | The globally unique identifier for the key |
| <a name="output_kms_key_policy"></a> [kms\_key\_policy](#output\_kms\_key\_policy) | The IAM resource policy set on the key |
| <a name="output_node_iam_role_arn"></a> [node\_iam\_role\_arn](#output\_node\_iam\_role\_arn) | EKS Auto node IAM role ARN |
| <a name="output_node_iam_role_name"></a> [node\_iam\_role\_name](#output\_node\_iam\_role\_name) | EKS Auto node IAM role name |
| <a name="output_node_iam_role_unique_id"></a> [node\_iam\_role\_unique\_id](#output\_node\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role |
| <a name="output_node_security_group_arn"></a> [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group |
| <a name="output_node_security_group_id"></a> [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group |
| <a name="output_oidc_provider"></a> [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) |

View File

@@ -3,7 +3,14 @@ provider "aws" {
}
data "aws_caller_identity" "current" {}
data "aws_availability_zones" "available" {}
data "aws_availability_zones" "available" {
# Exclude local zones
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
locals {
name = "ex-${replace(basename(path.cwd), "_", "-")}"

View File

@@ -142,12 +142,12 @@ output "cluster_tls_certificate_sha1_fingerprint" {
################################################################################
output "cluster_iam_role_name" {
description = "IAM role name of the EKS cluster"
description = "Cluster IAM role name"
value = module.eks.cluster_iam_role_name
}
output "cluster_iam_role_arn" {
description = "IAM role ARN of the EKS cluster"
description = "Cluster IAM role ARN"
value = module.eks.cluster_iam_role_arn
}
@@ -156,6 +156,25 @@ output "cluster_iam_role_unique_id" {
value = module.eks.cluster_iam_role_unique_id
}
################################################################################
# EKS Auto Node IAM Role
################################################################################
output "node_iam_role_name" {
description = "EKS Auto node IAM role name"
value = module.eks.node_iam_role_name
}
output "node_iam_role_arn" {
description = "EKS Auto node IAM role ARN"
value = module.eks.node_iam_role_arn
}
output "node_iam_role_unique_id" {
description = "Stable and unique string identifying the IAM role"
value = module.eks.node_iam_role_unique_id
}
################################################################################
# EKS Addons
################################################################################

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
}
}

View File

@@ -44,12 +44,24 @@ variable "authentication_mode" {
default = "API_AND_CONFIG_MAP"
}
variable "cluster_compute_config" {
description = "Configuration block for the cluster compute configuration"
type = any
default = {}
}
variable "cluster_upgrade_policy" {
description = "Configuration block for the cluster upgrade policy"
type = any
default = {}
}
variable "cluster_remote_network_config" {
description = "Configuration block for the cluster remote network configuration"
type = any
default = {}
}
variable "cluster_zonal_shift_config" {
description = "Configuration block for the cluster zonal shift"
type = any
@@ -434,7 +446,7 @@ variable "custom_oidc_thumbprints" {
################################################################################
variable "create_iam_role" {
description = "Determines whether a an IAM role is created or to use an existing IAM role"
description = "Determines whether an IAM role is created for the cluster"
type = bool
default = true
}
@@ -458,7 +470,7 @@ variable "iam_role_use_name_prefix" {
}
variable "iam_role_path" {
description = "Cluster IAM role path"
description = "The IAM role path"
type = string
default = null
}
@@ -481,6 +493,13 @@ variable "iam_role_additional_policies" {
default = {}
}
# TODO - will be removed in next breaking change; user can add the policy on their own when needed
variable "enable_security_groups_for_pods" {
description = "Determines whether to add the necessary IAM permission policy for security groups for pods"
type = bool
default = true
}
variable "iam_role_tags" {
description = "A map of additional tags to add to the IAM role created"
type = map(string)
@@ -549,6 +568,70 @@ variable "cluster_identity_providers" {
default = {}
}
################################################################################
# EKS Auto Node IAM Role
################################################################################
variable "create_node_iam_role" {
description = "Determines whether an EKS Auto node IAM role is created"
type = bool
default = true
}
variable "node_iam_role_name" {
description = "Name to use on the EKS Auto node IAM role created"
type = string
default = null
}
variable "node_iam_role_use_name_prefix" {
description = "Determines whether the EKS Auto node IAM role name (`node_iam_role_name`) is used as a prefix"
type = bool
default = true
}
variable "node_iam_role_path" {
description = "The EKS Auto node IAM role path"
type = string
default = null
}
variable "node_iam_role_description" {
description = "Description of the EKS Auto node IAM role"
type = string
default = null
}
variable "node_iam_role_permissions_boundary" {
description = "ARN of the policy that is used to set the permissions boundary for the EKS Auto node IAM role"
type = string
default = null
}
variable "node_iam_role_additional_policies" {
description = "Additional policies to be added to the EKS Auto node IAM role"
type = map(string)
default = {}
}
variable "node_iam_role_tags" {
description = "A map of additional tags to add to the EKS Auto node IAM role created"
type = map(string)
default = {}
}
variable "enable_node_custom_tags_permissions" {
description = "Determines whether to enable permissions for custom tags for the EKS Auto node IAM role"
type = bool
default = true
}
variable "node_iam_role_policy_statements" {
description = "A list of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) - used for adding specific IAM permissions as needed"
type = any
default = []
}
################################################################################
# Fargate
################################################################################

View File

@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.75"
version = ">= 5.79"
}
tls = {
source = "hashicorp/tls"