From 2b694828072439bb125ae3db57c78516709a45b7 Mon Sep 17 00:00:00 2001 From: Bryant Biggs Date: Fri, 28 Oct 2022 10:09:17 -0400 Subject: [PATCH] fix: Updates from testing with Outposts, still need final remote validation hence the git push --- examples/outposts/README.md | 40 +++-- examples/outposts/main.tf | 166 ++++++++++++----- examples/outposts/outputs.tf | 79 --------- examples/outposts/prerequisites/main.tf | 177 +++++++++++++++++++ examples/outposts/prerequisites/outputs.tf | 4 + examples/outposts/prerequisites/variables.tf | 5 + examples/outposts/prerequisites/versions.tf | 10 ++ examples/outposts/variables.tf | 7 +- main.tf | 41 +++-- node_groups.tf | 4 +- 10 files changed, 373 insertions(+), 160 deletions(-) create mode 100644 examples/outposts/prerequisites/main.tf create mode 100644 examples/outposts/prerequisites/outputs.tf create mode 100644 examples/outposts/prerequisites/variables.tf create mode 100644 examples/outposts/prerequisites/versions.tf diff --git a/examples/outposts/README.md b/examples/outposts/README.md index 7e6ebd4928..7de18c21cc 100644 --- a/examples/outposts/README.md +++ b/examples/outposts/README.md @@ -10,10 +10,25 @@ Note: This example requires an an AWS Outpost to provision. To run this example you need to: -1. Copy the `terraform.tfvars.example` to `terraform.tfvars` and fill in the required variables -2. Execute: +1. Deploy the remote host where the cluster will be provisioned from. The remote host is required since only private access is permitted to clusters created on Outposts. If you have access to the network where Outposts are provisioned (VPN, etc.), you can skip this step: ```bash +$ cd prerequisites +$ terraform init +$ terraform plan +$ terraform apply +``` + +2. If provisioning using the remote host deployed in step 1, connect to the remote host using SSM. Note, you will need to have the [SSM plugin for the AWS CLI installed](https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html). You can use the output generated by step 1 to connect: + +```bash +$ aws ssm start-session --region --target +``` + +3. Once connected to the remote host, navigate to the cloned project example directory and deploy the example: + +```bash +$ cd $HOME/terraform-aws-eks/examples/outposts $ terraform init $ terraform plan $ terraform apply @@ -35,27 +50,31 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| | [aws](#provider\_aws) | >= 4.34 | +| [kubernetes](#provider\_kubernetes) | >= 2.10 | ## Modules | Name | Source | Version | |------|--------|---------| | [eks](#module\_eks) | ../.. | n/a | -| [vpc\_cni\_irsa](#module\_vpc\_cni\_irsa) | terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks | ~> 5.0 | ## Resources | Name | Type | |------|------| +| [kubernetes_storage_class_v1.this](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/storage_class_v1) | resource | +| [aws_outposts_outpost_instance_types.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/outposts_outpost_instance_types) | data source | | [aws_outposts_outposts.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/outposts_outposts) | data source | +| [aws_subnet.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnet) | data source | +| [aws_subnets.lookup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | | [aws_subnets.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/subnets) | data source | +| [aws_vpc.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [outpost\_instance\_type](#input\_outpost\_instance\_type) | Instance type supported by the Outposts instance | `string` | `"m5.large"` | no | -| [region](#input\_region) | The AWS region to deploy into (e.g. us-east-1) | `string` | n/a | yes | +| [region](#input\_region) | The AWS region to deploy into (e.g. us-east-1) | `string` | `"us-west-2"` | no | ## Outputs @@ -64,7 +83,6 @@ Note that this example may create resources which cost money. Run `terraform des | [aws\_auth\_configmap\_yaml](#output\_aws\_auth\_configmap\_yaml) | Formatted yaml output for base aws-auth configmap containing roles used in cluster node groups/fargate profiles | | [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | Arn of cloudwatch log group created | | [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of cloudwatch log group created | -| [cluster\_addons](#output\_cluster\_addons) | Map of attribute maps for all EKS cluster addons enabled | | [cluster\_arn](#output\_cluster\_arn) | The Amazon Resource Name (ARN) of the cluster | | [cluster\_certificate\_authority\_data](#output\_cluster\_certificate\_authority\_data) | Base64 encoded certificate data required to communicate with the cluster | | [cluster\_endpoint](#output\_cluster\_endpoint) | Endpoint for your Kubernetes API server | @@ -72,24 +90,14 @@ Note that this example may create resources which cost money. Run `terraform des | [cluster\_iam\_role\_name](#output\_cluster\_iam\_role\_name) | IAM role name of the EKS cluster | | [cluster\_iam\_role\_unique\_id](#output\_cluster\_iam\_role\_unique\_id) | Stable and unique string identifying the IAM role | | [cluster\_id](#output\_cluster\_id) | The name/id of the EKS cluster. Will block on cluster creation until the cluster is really ready | -| [cluster\_identity\_providers](#output\_cluster\_identity\_providers) | Map of attribute maps for all EKS identity providers enabled | | [cluster\_oidc\_issuer\_url](#output\_cluster\_oidc\_issuer\_url) | The URL on the EKS cluster for the OpenID Connect identity provider | | [cluster\_platform\_version](#output\_cluster\_platform\_version) | Platform version for the cluster | | [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 | | [cluster\_security\_group\_arn](#output\_cluster\_security\_group\_arn) | Amazon Resource Name (ARN) of the cluster security group | | [cluster\_security\_group\_id](#output\_cluster\_security\_group\_id) | ID of the cluster security group | | [cluster\_status](#output\_cluster\_status) | Status of the EKS cluster. One of `CREATING`, `ACTIVE`, `DELETING`, `FAILED` | -| [cluster\_tls\_certificate\_sha1\_fingerprint](#output\_cluster\_tls\_certificate\_sha1\_fingerprint) | The SHA1 fingerprint of the public key of the cluster's certificate | -| [eks\_managed\_node\_groups](#output\_eks\_managed\_node\_groups) | Map of attribute maps for all EKS managed node groups created | -| [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 | -| [fargate\_profiles](#output\_fargate\_profiles) | Map of attribute maps for all EKS Fargate Profiles created | -| [kms\_key\_arn](#output\_kms\_key\_arn) | The Amazon Resource Name (ARN) of the key | -| [kms\_key\_id](#output\_kms\_key\_id) | The globally unique identifier for the key | -| [kms\_key\_policy](#output\_kms\_key\_policy) | The IAM resource policy set on the key | | [node\_security\_group\_arn](#output\_node\_security\_group\_arn) | Amazon Resource Name (ARN) of the node shared security group | | [node\_security\_group\_id](#output\_node\_security\_group\_id) | ID of the node shared security group | -| [oidc\_provider](#output\_oidc\_provider) | The OpenID Connect identity provider (issuer URL without leading `https://`) | -| [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider if `enable_irsa = true` | | [self\_managed\_node\_groups](#output\_self\_managed\_node\_groups) | Map of attribute maps for all self managed node groups created | | [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 | diff --git a/examples/outposts/main.tf b/examples/outposts/main.tf index bee2f31aa1..ea4d5dc64c 100644 --- a/examples/outposts/main.tf +++ b/examples/outposts/main.tf @@ -9,8 +9,7 @@ provider "kubernetes" { 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_id] + args = ["eks", "get-token", "--cluster-id", module.eks.cluster_id, "--region", var.region] } } @@ -18,6 +17,9 @@ locals { name = "ex-${basename(path.cwd)}" cluster_version = "1.21" # Required by EKS on Outposts + outpost_arn = element(tolist(data.aws_outposts_outposts.this.arns), 0) + instance_type = element(tolist(data.aws_outposts_outpost_instance_types.this.instance_types), 0) + tags = { Example = local.name GithubRepo = "terraform-aws-eks" @@ -32,84 +34,158 @@ locals { module "eks" { source = "../.." - cluster_name = local.name - cluster_version = local.cluster_version - cluster_endpoint_public_access = true + cluster_name = local.name + cluster_version = local.cluster_version + + cluster_endpoint_public_access = false # Not available on Outpost + cluster_endpoint_private_access = true + + vpc_id = data.aws_vpc.this.id + subnet_ids = data.aws_subnets.this.ids outpost_config = { - control_plane_instance_type = var.outpost_instance_type - outpost_arns = [tolist(data.aws_outposts_outposts.this.arns)[0]] + control_plane_instance_type = local.instance_type + outpost_arns = [local.outpost_arn] } - cluster_addons = { - coredns = { - most_recent = true + # Extend cluster security group rules + cluster_security_group_additional_rules = { + ingress_vpc_https = { + description = "Remote host to control plane" + protocol = "tcp" + from_port = 443 + to_port = 443 + type = "ingress" + cidr_blocks = [data.aws_vpc.this.cidr_block] } - kube-proxy = { - most_recent = true + inress_nodes_ephemeral_ports_tcp = { + description = "To node 1025-65535" + protocol = "tcp" + from_port = 1025 + to_port = 65535 + type = "ingress" + source_node_security_group = true } - vpc-cni = { - most_recent = true - service_account_role_arn = module.vpc_cni_irsa.iam_role_arn + egress_nodes_ephemeral_ports_tcp = { + description = "To node 1025-65535" + protocol = "tcp" + from_port = 1025 + to_port = 65535 + type = "egress" + source_node_security_group = true } } - # Encryption key - create_kms_key = true - cluster_encryption_config = { - resources = ["secrets"] + # Extend node-to-node security group rules + node_security_group_additional_rules = { + ingress_vpc_all = { + description = "VPC" + protocol = "-1" + from_port = 0 + to_port = 0 + type = "ingress" + cidr_blocks = [data.aws_vpc.this.cidr_block] + } + ingress_self_all = { + description = "Node to node all ports/protocols" + protocol = "-1" + from_port = 0 + to_port = 0 + type = "ingress" + self = true + } + egress_all = { + description = "Node all egress" + protocol = "-1" + from_port = 0 + to_port = 0 + type = "egress" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + } } - kms_key_deletion_window_in_days = 7 - enable_kms_key_rotation = true - - create_cluster_security_group = false - create_node_security_group = false - subnet_ids = [tolist(data.aws_subnets.this.ids)[0]] - - manage_aws_auth_configmap = true - - eks_managed_node_group_defaults = { - instance_types = [var.outpost_instance_type] + self_managed_node_group_defaults = { attach_cluster_primary_security_group = true + + iam_role_additional_policies = { + AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + } } - eks_managed_node_groups = { + self_managed_node_groups = { outpost = { name = local.name + + min_size = 2 + max_size = 5 + desired_size = 3 + instance_type = local.instance_type } } + # We need to add the node group IAM role to the aws-auth configmap + create_aws_auth_configmap = true + tags = local.tags } +resource "kubernetes_storage_class_v1" "this" { + metadata { + name = "ebs-sc" + annotations = { + "storageclass.kubernetes.io/is-default-class" = "true" + } + } + + storage_provisioner = "ebs.csi.aws.com" + volume_binding_mode = "WaitForFirstConsumer" + allow_volume_expansion = true + + parameters = { + type = "gp2" + encrypted = "true" + } +} + ################################################################################ # Supporting Resources ################################################################################ data "aws_outposts_outposts" "this" {} -data "aws_subnets" "this" { +data "aws_outposts_outpost_instance_types" "this" { + arn = local.outpost_arn +} + +# This just grabs the first Outpost and returns its subnets +data "aws_subnets" "lookup" { filter { name = "outpost-arn" - values = [tolist(data.aws_outposts_outposts.this.arns)[0]] + values = [local.outpost_arn] } } -module "vpc_cni_irsa" { - source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" - version = "~> 5.0" +# This grabs a single subnet to reverse lookup those that belong to same VPC +# This is whats used for the cluster +data "aws_subnet" "this" { + id = element(tolist(data.aws_subnets.lookup.ids), 0) +} - role_name_prefix = "VPC-CNI-IRSA" - attach_vpc_cni_policy = true - vpc_cni_enable_ipv4 = true +# These are subnets for the Outpost and restricted to the same VPC +# This is whats used for the cluster +data "aws_subnets" "this" { + filter { + name = "outpost-arn" + values = [local.outpost_arn] + } - oidc_providers = { - main = { - provider_arn = module.eks.oidc_provider_arn - namespace_service_accounts = ["kube-system:aws-node"] - } + filter { + name = "vpc-id" + values = [data.aws_subnet.this.vpc_id] } +} - tags = local.tags +data "aws_vpc" "this" { + id = data.aws_subnet.this.vpc_id } diff --git a/examples/outposts/outputs.tf b/examples/outposts/outputs.tf index 6e31908292..b71fd86379 100644 --- a/examples/outposts/outputs.tf +++ b/examples/outposts/outputs.tf @@ -42,25 +42,6 @@ output "cluster_primary_security_group_id" { value = module.eks.cluster_primary_security_group_id } -################################################################################ -# 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 ################################################################################ @@ -89,25 +70,6 @@ output "node_security_group_id" { 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 ################################################################################ @@ -127,24 +89,6 @@ output "cluster_iam_role_unique_id" { 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 ################################################################################ @@ -159,29 +103,6 @@ output "cloudwatch_log_group_arn" { 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 ################################################################################ diff --git a/examples/outposts/prerequisites/main.tf b/examples/outposts/prerequisites/main.tf new file mode 100644 index 0000000000..e3f765e120 --- /dev/null +++ b/examples/outposts/prerequisites/main.tf @@ -0,0 +1,177 @@ +provider "aws" { + region = var.region +} + +locals { + name = "ex-${basename(path.cwd)}" + + terraform_version = "1.3.3" + + outpost_arn = element(tolist(data.aws_outposts_outposts.this.arns), 0) + instance_type = element(tolist(data.aws_outposts_outpost_instance_types.this.instance_types), 0) + + tags = { + Example = local.name + GithubRepo = "terraform-aws-eks" + GithubOrg = "terraform-aws-modules" + } +} + +################################################################################ +# Pre-Requisites +################################################################################ + +resource "aws_iam_role" "ec2" { + name_prefix = "${local.name}-bastion" + + # Using admin to be able to provision resources from remote host + managed_policy_arns = ["arn:aws:iam::aws:policy/AdministratorAccess"] + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + }, + ] + }) + + tags = local.tags +} + +resource "aws_iam_instance_profile" "ec2" { + name = "${local.name}-bastion" + role = aws_iam_role.ec2.name +} + +data "aws_ssm_parameter" "al2" { + name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" +} + +module "ssm_bastion_ec2" { + source = "terraform-aws-modules/ec2-instance/aws" + version = "~> 4.0" + + name = "${local.name}-bastion" + + ami = data.aws_ssm_parameter.al2.value + instance_type = local.instance_type + iam_instance_profile = aws_iam_instance_profile.ec2.name + + user_data = <<-EOT + #!/bin/bash + + # Add ssm-user since it won't exist until first login + adduser -m ssm-user + tee /etc/sudoers.d/ssm-agent-users <<'EOF' + # User rules for ssm-user + ssm-user ALL=(ALL) NOPASSWD:ALL + EOF + chmod 440 /etc/sudoers.d/ssm-agent-users + + cd /home/ssm-user + + # Install git to clone repo + yum install git -y + + # Install Terraform + curl -sSO https://releases.hashicorp.com/terraform/${local.terraform_version}/terraform_${local.terraform_version}_linux_amd64.zip + sudo unzip -qq terraform_${local.terraform_version}_linux_amd64.zip terraform -d /usr/bin/ + rm terraform_${local.terraform_version}_linux_amd64.zip 2> /dev/null + + # Install kubectl + curl -LO https://dl.k8s.io/release/v1.21.0/bin/linux/amd64/kubectl + install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl + + # Remove default awscli which is v1 - we want latest v2 + yum remove awscli -y + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip -qq awscliv2.zip + ./aws/install + + # Clone repo + git clone https://github.com/bryantbiggs/terraform-aws-eks.git \ + && cd /home/ssm-user/terraform-aws-eks \ + && git checkout refactor/v19 + + chown -R ssm-user:ssm-user /home/ssm-user/ + EOT + + vpc_security_group_ids = [module.bastion_security_group.security_group_id] + subnet_id = element(data.aws_subnets.this.ids, 0) + + tags = local.tags +} + +module "bastion_security_group" { + source = "terraform-aws-modules/security-group/aws" + version = "~> 4.0" + + name = "${local.name}-bastion" + description = "Security group to allow provisioning ${local.name} EKS local cluster on Outposts" + vpc_id = data.aws_vpc.this.id + + ingress_with_cidr_blocks = [ + { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = data.aws_vpc.this.cidr_block + }, + ] + egress_with_cidr_blocks = [ + { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = "0.0.0.0/0" + }, + ] + + tags = local.tags +} + +################################################################################ +# Supporting Resources +################################################################################ + +data "aws_outposts_outposts" "this" {} + +data "aws_outposts_outpost_instance_types" "this" { + arn = local.outpost_arn +} + +# This just grabs the first Outpost and returns its subnets +data "aws_subnets" "lookup" { + filter { + name = "outpost-arn" + values = [local.outpost_arn] + } +} + +# This grabs a single subnet to reverse lookup those that belong to same VPC +# This is whats used for the cluster +data "aws_subnet" "this" { + id = element(tolist(data.aws_subnets.lookup.ids), 0) +} + +# These are subnets for the Outpost and restricted to the same VPC +# This is whats used for the cluster +data "aws_subnets" "this" { + filter { + name = "outpost-arn" + values = [local.outpost_arn] + } + + filter { + name = "vpc-id" + values = [data.aws_subnet.this.vpc_id] + } +} + +data "aws_vpc" "this" { + id = data.aws_subnet.this.vpc_id +} diff --git a/examples/outposts/prerequisites/outputs.tf b/examples/outposts/prerequisites/outputs.tf new file mode 100644 index 0000000000..f2ff81ab70 --- /dev/null +++ b/examples/outposts/prerequisites/outputs.tf @@ -0,0 +1,4 @@ +output "ssm_start_session" { + description = "SSM start session command to connect to remote host created" + value = "aws ssm start-session --region ${var.region} --target ${module.ssm_bastion_ec2.id}" +} diff --git a/examples/outposts/prerequisites/variables.tf b/examples/outposts/prerequisites/variables.tf new file mode 100644 index 0000000000..47945c8501 --- /dev/null +++ b/examples/outposts/prerequisites/variables.tf @@ -0,0 +1,5 @@ +variable "region" { + description = "The AWS region to deploy into (e.g. us-east-1)" + type = string + default = "us-west-2" +} diff --git a/examples/outposts/prerequisites/versions.tf b/examples/outposts/prerequisites/versions.tf new file mode 100644 index 0000000000..5f058b4c11 --- /dev/null +++ b/examples/outposts/prerequisites/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.34" + } + } +} diff --git a/examples/outposts/variables.tf b/examples/outposts/variables.tf index be8639ed0e..47945c8501 100644 --- a/examples/outposts/variables.tf +++ b/examples/outposts/variables.tf @@ -1,10 +1,5 @@ variable "region" { description = "The AWS region to deploy into (e.g. us-east-1)" type = string -} - -variable "outpost_instance_type" { - description = "Instance type supported by the Outposts instance" - type = string - default = "m5.large" + default = "us-west-2" } diff --git a/main.tf b/main.tf index f6542fcdd9..652ae9f0fa 100644 --- a/main.tf +++ b/main.tf @@ -6,7 +6,8 @@ locals { cluster_role = try(aws_iam_role.this[0].arn, var.iam_role_arn) - create_outposts_local_cluster = length(var.outpost_config) > 0 + create_outposts_local_cluster = length(var.outpost_config) > 0 + enable_cluster_encryption_config = length(var.cluster_encryption_config) > 0 && !local.create_outposts_local_cluster } ################################################################################ @@ -26,7 +27,7 @@ resource "aws_eks_cluster" "this" { subnet_ids = coalescelist(var.control_plane_subnet_ids, var.subnet_ids) endpoint_private_access = var.cluster_endpoint_private_access endpoint_public_access = var.cluster_endpoint_public_access - public_access_cidrs = var.cluster_endpoint_public_access_cidrs + public_access_cidrs = var.cluster_endpoint_public_access ? var.cluster_endpoint_public_access_cidrs : [] } dynamic "kubernetes_network_config" { @@ -51,7 +52,7 @@ resource "aws_eks_cluster" "this" { dynamic "encryption_config" { # Not available on Outposts - for_each = length(var.cluster_encryption_config) > 0 && !local.create_outposts_local_cluster ? [var.cluster_encryption_config] : [] + for_each = local.enable_cluster_encryption_config ? [var.cluster_encryption_config] : [] content { provider { @@ -218,13 +219,15 @@ resource "aws_security_group_rule" "cluster" { ################################################################################ data "tls_certificate" "this" { - count = local.create && var.enable_irsa ? 1 : 0 + # Not available on outposts + count = local.create && var.enable_irsa && !local.create_outposts_local_cluster ? 1 : 0 url = aws_eks_cluster.this[0].identity[0].oidc[0].issuer } resource "aws_iam_openid_connect_provider" "oidc_provider" { - count = local.create && var.enable_irsa ? 1 : 0 + # Not available on outposts + count = local.create && var.enable_irsa && !local.create_outposts_local_cluster ? 1 : 0 client_id_list = distinct(compact(concat(["sts.${local.dns_suffix}"], var.openid_connect_audiences))) thumbprint_list = concat([data.tls_certificate.this[0].certificates[0].sha1_fingerprint], var.custom_oidc_thumbprints) @@ -261,7 +264,18 @@ data "aws_iam_policy_document" "assume_role_policy" { principals { type = "Service" - identifiers = local.create_outposts_local_cluster ? ["outposts.eks-local.${local.dns_suffix}"] : ["eks.${local.dns_suffix}"] + identifiers = ["eks.${local.dns_suffix}"] + } + + dynamic "principals" { + for_each = local.create_outposts_local_cluster ? [1] : [] + + content { + type = "Service" + identifiers = [ + "ec2.${local.dns_suffix}", + ] + } } } } @@ -307,7 +321,7 @@ 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.iam_role_policy_prefix}/AmazonEKSClusterPolicy", + 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 } @@ -324,14 +338,16 @@ resource "aws_iam_role_policy_attachment" "additional" { # Using separate attachment due to `The "for_each" value depends on resource attributes that cannot be determined until apply` resource "aws_iam_role_policy_attachment" "cluster_encryption" { - count = local.create_iam_role && var.attach_cluster_encryption_policy && length(var.cluster_encryption_config) > 0 ? 1 : 0 + # Encryption config not available on Outposts + count = local.create_iam_role && var.attach_cluster_encryption_policy && local.enable_cluster_encryption_config ? 1 : 0 policy_arn = aws_iam_policy.cluster_encryption[0].arn role = aws_iam_role.this[0].name } resource "aws_iam_policy" "cluster_encryption" { - count = local.create_iam_role && var.attach_cluster_encryption_policy && length(var.cluster_encryption_config) > 0 ? 1 : 0 + # Encryption config not available on Outposts + count = local.create_iam_role && var.attach_cluster_encryption_policy && local.enable_cluster_encryption_config ? 1 : 0 name = var.cluster_encryption_policy_use_name_prefix ? null : local.cluster_encryption_policy_name name_prefix = var.cluster_encryption_policy_use_name_prefix ? local.cluster_encryption_policy_name : null @@ -362,7 +378,8 @@ resource "aws_iam_policy" "cluster_encryption" { ################################################################################ resource "aws_eks_addon" "this" { - for_each = { for k, v in var.cluster_addons : k => v if local.create } + # Not supported on outposts + for_each = { for k, v in var.cluster_addons : k => v if local.create && !local.create_outposts_local_cluster } cluster_name = aws_eks_cluster.this[0].name addon_name = try(each.value.name, each.key) @@ -388,7 +405,7 @@ resource "aws_eks_addon" "this" { } data "aws_eks_addon_version" "this" { - for_each = { for k, v in var.cluster_addons : k => v if local.create } + for_each = { for k, v in var.cluster_addons : k => v if local.create && !local.create_outposts_local_cluster } addon_name = try(each.value.name, each.key) kubernetes_version = coalesce(var.cluster_version, aws_eks_cluster.this[0].version) @@ -401,7 +418,7 @@ data "aws_eks_addon_version" "this" { ################################################################################ resource "aws_eks_identity_provider_config" "this" { - for_each = { for k, v in var.cluster_identity_providers : k => v if local.create } + for_each = { for k, v in var.cluster_identity_providers : k => v if local.create && !local.create_outposts_local_cluster } cluster_name = aws_eks_cluster.this[0].name diff --git a/node_groups.tf b/node_groups.tf index 168152a37e..8e8d4407b7 100644 --- a/node_groups.tf +++ b/node_groups.tf @@ -207,7 +207,7 @@ resource "aws_security_group_rule" "node" { module "fargate_profile" { source = "./modules/fargate-profile" - for_each = { for k, v in var.fargate_profiles : k => v if var.create } + for_each = { for k, v in var.fargate_profiles : k => v if var.create && !local.create_outposts_local_cluster } create = try(each.value.create, true) @@ -243,7 +243,7 @@ module "fargate_profile" { module "eks_managed_node_group" { source = "./modules/eks-managed-node-group" - for_each = { for k, v in var.eks_managed_node_groups : k => v if var.create } + for_each = { for k, v in var.eks_managed_node_groups : k => v if var.create && !local.create_outposts_local_cluster } create = try(each.value.create, true)