From 2d99af7f8d10ec108903f5174907797c98f616cc Mon Sep 17 00:00:00 2001 From: clementbolin Date: Sat, 14 Sep 2024 01:30:25 +0700 Subject: [PATCH 1/6] feat(stable): configure eks cluster --- .gitignore | 1 + eks.tf | 230 +++++++++++++++++++++++---------------- example/main.tf | 56 +++++++++- example/terraform.tfvars | 2 +- main.tf | 27 +++++ variables.tf | 103 +++++++++++++++++- 6 files changed, 317 insertions(+), 102 deletions(-) create mode 100644 main.tf diff --git a/.gitignore b/.gitignore index 3fa8c86..8aa2026 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .terraform +.DS_Store diff --git a/eks.tf b/eks.tf index 803750f..7ad78df 100644 --- a/eks.tf +++ b/eks.tf @@ -11,127 +11,165 @@ module "iam" { } module "eks" { - source = "terraform-aws-modules/eks/aws" + source = "terraform-aws-modules/eks/aws" + version = "~> 20.20.0" - version = "20.5.0" + # create = var.create - cluster_name = var.cluster.name - cluster_version = var.cluster.version - cluster_endpoint_public_access = var.cluster.endpoint_public_access + node_security_group_use_name_prefix = true + cluster_security_group_use_name_prefix = true - enable_irsa = true - iam_role_arn = module.iam.cluster_iam_role_arn + cluster_name = var.cluster.name + cluster_version = var.cluster.version || "1.31" - create_kms_key = false - cluster_encryption_config = { - provider_key_arn = module.iam.kms_key_arn - resources = ["secrets"] - } + vpc_id = var.network.vpc_id + subnet_ids = var.network.subnet_ids - # Gives Terraform identity admin access to cluster which will - # allow deploying resources (Karpenter) into the cluster - enable_cluster_creator_admin_permissions = true + enable_irsa = true + cluster_endpoint_private_access = true - cluster_addons = { - coredns = { - configuration_values = jsonencode({ - computeType = "Fargate" - # Ensure that we fully utilize the minimum amount of resources that are supplied by - # Fargate https://docs.aws.amazon.com/eks/latest/userguide/fargate-pod-configuration.html - # Fargate adds 256 MB to each pod's memory reservation for the required Kubernetes - # components (kubelet, kube-proxy, and containerd). Fargate rounds up to the following - # compute configuration that most closely matches the sum of vCPU and memory requests in - # order to ensure pods always have the resources that they need to run. - resources = { - limits = { - cpu = "0.25" - # We are targeting the smallest Task size of 512Mb, so we subtract 256Mb from the - # request/limit to ensure we can fit within that task - memory = "256M" - } - requests = { - cpu = "0.25" - # We are targeting the smallest Task size of 512Mb, so we subtract 256Mb from the - # request/limit to ensure we can fit within that task - memory = "256M" - } - } - }) - } - kube-proxy = {} - vpc-cni = {} - } + create_iam_role = true - vpc_id = var.network.vpc_id - subnet_ids = var.network.subnet_ids - control_plane_subnet_ids = var.network.control_plane_subnet_ids + authentication_mode = "API_AND_CONFIG_MAP" + enable_cluster_creator_admin_permissions = true + # access_entries = merge( + # { for rolearn in lookup(local.admin_role_arns_customs, local.account_id, local.admin_role_arns_default) : + # rolearn => { + # principal_arn = rolearn + # type = "STANDARD" + # policy_associations = { + # admin = { + # policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy" + # access_scope = { + # type = "cluster" + # } + # } + # } + # } + # }, var.access_entries) # Fargate profiles use the cluster primary security group so these are not utilized - create_cluster_security_group = false - create_node_security_group = false + create_cluster_security_group = true + cluster_additional_security_group_ids = var.additional_sg_ids - fargate_profiles = local.fargate_profiles + create_node_security_group = true + node_security_group_additional_rules = var.node_security_group_additional_rules - tags = merge(var.tags, { - # NOTE - if creating multiple security groups with this module, only tag the - # security group that Karpenter should utilize with the following tag - # (i.e. - at most, only one security group should have this tag in your account) - "karpenter.sh/discovery" = var.cluster.name - }) -} + cluster_security_group_additional_rules = var.cluster_security_group_additional_rules -module "karpenter" { - source = "terraform-aws-modules/eks/aws//modules/karpenter" + cluster_endpoint_public_access = var.cluster.endpoint_public_access || true + cluster_endpoint_public_access_cidrs = var.endpoint_public_access_cidrs || ["0.0.0.0/0"] - version = "20.5.0" + create_kms_key = true + kms_key_administrators = var.auth.kms_key_administrators + # If you want to maintain the current default behavior of v19.x + kms_key_enable_default_policy = false - cluster_name = module.eks.cluster_name + # EKS Managed Node Group(s) + eks_managed_node_group_defaults = { + key_name = try(data.aws_key_pair.debug[0].key_name, null) + create_iam_role = false - # EKS Fargate currently does not support Pod Identity - enable_irsa = true - irsa_oidc_provider_arn = module.eks.oidc_provider_arn + ami_type = var.ami_type + disk_size = var.default_disk_size - # Used to attach additional IAM policies to the Karpenter node IAM role - node_iam_role_additional_policies = { - AmazonSSMManagedInstanceCore = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + tags = var.tags } + eks_managed_node_groups = local.node_group - tags = var.tags -} - -module "eks_auth" { - source = "terraform-aws-modules/eks/aws//modules/aws-auth" - version = "20.5.0" - - manage_aws_auth_configmap = true - - aws_auth_roles = [ + # Fargate profiles + fargate_profiles = merge( { - rolearn = "arn:aws:iam::478986666586:role/TrackitMonitoringAdmin" - username = "trackit-eks-admin" - groups = ["system:masters"] + for k, v in try(var.fargate.profiles, merge( + { + karpenter = { + selectors = [ + { namespace = "karpenter" } + ] + } + }, + { + kube_system = { + selectors = [ + { + namespace = "kube-system" + labels = { + k8s-app = "kube-dns" + } + } + ] + } + } + )) : k => { + selectors = v.selectors + } }, + ) + + # Non-blocking warning: resolve_conflicts deprecated attribute + # Will be Resolved in a future release : https://github.com/terraform-aws-modules/terraform-aws-eks/issues/2635 + cluster_addons = merge( + { kube-proxy = { + configuration_values = jsonencode({ + resources = { + limits = { + memory = "100M" + } + requests = { + cpu = "0.015" + memory = "100M" + } + } + }) + } }, { - rolearn = "arn:aws:iam::478986666586:role/adn-admins" - username = "adn-eks-admin" - groups = ["system:masters"] + coredns = { + configuration_values = jsonencode({ + computeType = "Fargate" + # Ensure that we fully utilize the minimum amount of resources that are supplied by + # Fargate https://docs.aws.amazon.com/eks/latest/userguide/fargate-pod-configuration.html + # Fargate adds 256 MB to each pod's memory reservation for the required Kubernetes + # components (kubelet, kube-proxy, and containerd). Fargate rounds up to the following + # compute configuration that most closely matches the sum of vCPU and memory requests in + # order to ensure pods always have the resources that they need to run. + resources = { + limits = { + # We are targeting the smallest Task size of 512Mb, so we subtract 256Mb from the + # request/limit to ensure we can fit within that task + memory = "256M" + } + requests = { + cpu = "0.25" + # We are targeting the smallest Task size of 512Mb, so we subtract 256Mb from the + # request/limit to ensure we can fit within that task + memory = "256M" + } + } + }) + } }, { - rolearn = module.karpenter.iam_role_arn - username = "system:node:{{EC2PrivateDNSName}}" - groups = ["system:bootstrappers", "system:nodes"] - } - ] + vpc-cni = { + service_account_role_arn = try(var.vpc_cni.iam_role_arn, module.irsa.vpc_cni_iam_role_arn) + configuration_values = jsonencode({ + env = { + # Reference docs https://docs.aws.amazon.com/eks/latest/userguide/cni-increase-ip-addresses.html + ENABLE_PREFIX_DELEGATION = "true" + WARM_PREFIX_TARGET = "1" + } + }) + } + }, + ) - aws_auth_users = [ - { - userarn = "arn:aws:iam::478986666586:user/trackit-eks" - username = "terraform-account" - groups = ["system:masters"] - } - ] -} + cluster_tags = var.tags + node_security_group_tags = merge( + var.node_security_group_tags, + local.karpenter_tags + ) + tags = var.tags +} resource "helm_release" "karpenter" { namespace = "karpenter" diff --git a/example/main.tf b/example/main.tf index 78ea145..79f3749 100644 --- a/example/main.tf +++ b/example/main.tf @@ -16,7 +16,7 @@ module "eks" { } kms_key_administrators = [ - "arn:aws:iam::478986666586:user/trackit-eks", + "arn:aws:iam::XXXXXXXX:user/trackit-eks", ] ecr_token = { @@ -25,7 +25,59 @@ module "eks" { } env = "staging" - zone_name = "adn.tech" + zone_name = "XXXX.tech" tags = var.tags } + +resource "kubectl_manifest" "karpenter_node_class" { + yaml_body = <<-YAML + apiVersion: karpenter.k8s.aws/v1beta1 + kind: EC2NodeClass + metadata: + name: default + spec: + amiFamily: AL2 + role: ${module.karpenter.node_iam_role_name} + subnetSelectorTerms: + - tags: + karpenter.sh/discovery: ${module.eks.cluster_name} + securityGroupSelectorTerms: + - tags: + karpenter.sh/discovery: ${module.eks.cluster_name} + tags: + karpenter.sh/discovery: ${module.eks.cluster_name} + YAML +} + +resource "kubectl_manifest" "karpenter_node_pool" { + yaml_body = <<-YAML + apiVersion: karpenter.sh/v1beta1 + kind: NodePool + metadata: + name: default + spec: + template: + spec: + nodeClassRef: + name: default + requirements: + - key: "karpenter.k8s.aws/instance-category" + operator: In + values: ["c", "m", "r"] + - key: "karpenter.k8s.aws/instance-cpu" + operator: In + values: ["4", "8", "16", "32"] + - key: "karpenter.k8s.aws/instance-hypervisor" + operator: In + values: ["nitro"] + - key: "karpenter.k8s.aws/instance-generation" + operator: Gt + values: ["2"] + limits: + cpu: 1000 + disruption: + consolidationPolicy: WhenEmpty + consolidateAfter: 30s + YAML +} diff --git a/example/terraform.tfvars b/example/terraform.tfvars index 99ab9b2..72a9fb7 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -6,7 +6,7 @@ vpc = { azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] public_subnets = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"] - subnet_ids = ["subnet-053ec5a7557a62dd0", "subnet-03c80c595a93c7b36", "subnet-0322b7da3cdebca2b"] + subnet_ids = ["subnet-XXXXXXXXXX", "subnet-XXXXXXX", "subnet-XXXXXXXX"] enable_nat_gateway = true create_igw = true } diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..d56ed21 --- /dev/null +++ b/main.tf @@ -0,0 +1,27 @@ +locals { + node_group = var.node_groups == {} ? {} : { + for node in flatten([ + for i, subnet in data.aws_subnet.selected : [ + for name, node_group in var.node_groups : + merge( + { + name = "${name}-${i}", + subnet_ids = [subnet.id], + create_launch_template = true + use_custom_launch_template = true + use_name_prefix = false + create_iam_role = false + iam_role_arn = var.node_group_iam_role_arn + vpc_security_group_ids = var.node_additional_security_group_ids + }, + node_group, + ) + ] + ]) : + node.name => node + } + + karpenter_tags = { + "karpenter.sh/discovery" = var.cluster.name + } +} diff --git a/variables.tf b/variables.tf index 6b1f500..6f13f1e 100644 --- a/variables.tf +++ b/variables.tf @@ -1,9 +1,10 @@ variable "cluster" { description = "EKS cluster configuration" type = object({ - version = string - name = string - endpoint_public_access = bool + version = string + name = string + endpoint_public_access = bool + endpoint_public_access_cidrs = list(string) }) } @@ -16,6 +17,14 @@ variable "network" { }) } +variable "auth" { + description = "Auth configuration" + type = object({ + admin_role_arns = list(string) + kms_key_administrators = list(string) + }) +} + variable "ecr_token" { description = "ECR token" type = object({ @@ -60,3 +69,91 @@ variable "private_hosted_zone_additional_vpc_ids_association" { type = list(string) default = [] } + +variable "aws_auth_role_arns" { + description = "AWS auth role ARNs, used for EKS auth config map" + type = list(string) +} + +variable "tags" { + description = "Tags" + type = map(string) + default = { + "service" = "eks_terraform" + } +} + +variable "additional_sg_ids" { + description = "List of additional, externally created security group IDs to attach to the cluster control plane" + type = list(string) + default = [] +} + +variable "node_security_group_additional_rules" { + description = "Additional rules for the node security group" + type = list(object({ + description = string + from_port = number + to_port = number + protocol = string + cidr_blocks = list(string) + security_groups = list(string) + self = bool + prefix_list_ids = list(string) + ipv6_cidr_blocks = list(string) + })) + default = [] + +} + +variable "cluster_security_group_additional_rules" { + description = "Additional rules for the cluster security group" + type = list(object({ + description = string + from_port = number + to_port = number + protocol = string + cidr_blocks = list(string) + security_groups = list(string) + self = bool + prefix_list_ids = list(string) + ipv6_cidr_blocks = list(string) + })) + default = [] +} + +variable "ami_type" { + description = "node groups AMI type" + type = string + default = "AL2_x86_64" +} + +variable "default_disk_size" { + description = "Default EBS disk size" + type = number + default = null +} + +variable "fargate" { + description = "Fargate configuration values" + type = any + default = {} +} + + + + + +variable "tags" { + description = "Tags" + type = map(string) + default = { + "service" = "eks_terraform" + } +} + +variable "node_security_group_tags" { + description = "Tags for the node security group" + type = map(string) + default = {} +} From 3e7369557af10910b94073d6106d5924ef577525 Mon Sep 17 00:00:00 2001 From: clementbolin Date: Sat, 14 Sep 2024 01:34:46 +0700 Subject: [PATCH 2/6] fix: node group configuration --- variables.tf | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/variables.tf b/variables.tf index 6f13f1e..a214e82 100644 --- a/variables.tf +++ b/variables.tf @@ -140,10 +140,6 @@ variable "fargate" { default = {} } - - - - variable "tags" { description = "Tags" type = map(string) @@ -157,3 +153,21 @@ variable "node_security_group_tags" { type = map(string) default = {} } + +variable "node_groups" { + description = "Node Groups for the EKS cluster" + type = map(any) + default = {} +} + +variable "node_group_iam_role_arn" { + description = "Existing IAM role ARN for the Node groups" + type = string + default = null +} + +variable "node_additional_security_group_ids" { + description = "List of additional security group ids to add to the node security group created" + type = list(string) + default = [] +} From 81dd16662465eb36cab360527f6fd0fdd543276b Mon Sep 17 00:00:00 2001 From: clementbolin Date: Sun, 15 Sep 2024 00:12:34 +0700 Subject: [PATCH 3/6] chore: refactor auth & iam configuration --- auth.tf | 8 ++++ eks.tf | 14 ------ iam.tf | 8 ++++ modules/auth/main.tf | 68 ++++++----------------------- modules/auth/rbac.tf | 17 -------- modules/auth/variables.tf | 52 ++++++++-------------- modules/iam/cluster.tf | 88 -------------------------------------- modules/iam/datasources.tf | 34 --------------- modules/iam/kms.tf | 47 -------------------- modules/iam/locals.tf | 12 ------ modules/iam/main.tf | 45 +++++++++++++++++++ modules/iam/node.tf | 33 -------------- modules/iam/outputs.tf | 30 ++++++------- modules/iam/variables.tf | 68 ++++------------------------- route53.tf | 25 +---------- 15 files changed, 116 insertions(+), 433 deletions(-) create mode 100644 auth.tf create mode 100644 iam.tf delete mode 100644 modules/auth/rbac.tf delete mode 100644 modules/iam/cluster.tf delete mode 100644 modules/iam/datasources.tf delete mode 100644 modules/iam/kms.tf delete mode 100644 modules/iam/locals.tf create mode 100644 modules/iam/main.tf delete mode 100644 modules/iam/node.tf diff --git a/auth.tf b/auth.tf new file mode 100644 index 0000000..a8de7df --- /dev/null +++ b/auth.tf @@ -0,0 +1,8 @@ +module "auth" { + source = "./modules/auth" + + manage_aws_auth_configmap = var.auth.manage_aws_auth_configmap + aws_auth_accounts = var.auth.aws_auth_accounts + aws_auth_users = var.auth.aws_auth_users + aws_auth_roles = var.auth.aws_auth_roles +} diff --git a/eks.tf b/eks.tf index 7ad78df..74dfd91 100644 --- a/eks.tf +++ b/eks.tf @@ -1,21 +1,7 @@ -module "iam" { - source = "./modules/iam" - - cluster_name = var.cluster.name - - aws_region_short = var.aws_region_short - - create_node_group_iam_role = false - - kms_key_administrators = var.kms_key_administrators -} - module "eks" { source = "terraform-aws-modules/eks/aws" version = "~> 20.20.0" - # create = var.create - node_security_group_use_name_prefix = true cluster_security_group_use_name_prefix = true diff --git a/iam.tf b/iam.tf new file mode 100644 index 0000000..adee8de --- /dev/null +++ b/iam.tf @@ -0,0 +1,8 @@ +module "iam" { + source = "./modules/iam" + + cluster_name = var.cluster.name + cluster_oidc_provider_arns = module.eks.oidc_provider_arns + + tags = var.tags +} diff --git a/modules/auth/main.tf b/modules/auth/main.tf index e5088ed..4bf2ac7 100644 --- a/modules/auth/main.tf +++ b/modules/auth/main.tf @@ -1,56 +1,14 @@ -locals { - node_iam_role_arns = var.node_iam_role_arns - - aws_auth_configmap_data = { - mapRoles = yamlencode(concat( - [for arn in local.node_iam_role_arns : { - rolearn = arn - username = "system:node:{{EC2PrivateDNSName}}" - groups = [ - "system:bootstrappers", - "system:nodes", - ] - } - ], - [ - for role_arn in var.fargate_profile_pod_execution_role_arns : { - rolearn = role_arn - username = "system:node:{{SessionName}}" - groups = [ - "system:bootstrappers", - "system:nodes", - "system:node-proxier", - ] - } - ], - [ - for arn in var.admin_role_arns : { - rolearn = arn, - username = "eks-admin", - groups = ["system:masters"] - } - ], - [ - for arn in var.read_only_role_arns : { - rolearn = arn, - username = "eks-readonly", - groups = ["readonly"] - } - ], - var.aws_auth_roles - )) - mapUsers = yamlencode(var.aws_auth_users) - mapAccounts = yamlencode(var.aws_auth_accounts) - } -} - -resource "kubernetes_config_map_v1_data" "aws_auth" { - force = true - - metadata { - name = "aws-auth" - namespace = "kube-system" - } - - data = local.aws_auth_configmap_data +module "aws_auth" { + source = "terraform-aws-modules/eks/aws//modules/aws-auth" + version = "~> 20.20.0" + + manage_aws_auth_configmap = var.manage_aws_auth_configmap + aws_auth_accounts = var.aws_auth_accounts + aws_auth_users = var.aws_auth_users + aws_auth_roles = concat( + # Extra auth roles + module.aws_auth_extra.aws_auth_roles, + # Custom Auth roles + var.aws_auth_roles, + ) } diff --git a/modules/auth/rbac.tf b/modules/auth/rbac.tf deleted file mode 100644 index bfc194f..0000000 --- a/modules/auth/rbac.tf +++ /dev/null @@ -1,17 +0,0 @@ -resource "kubectl_manifest" "readonly_clusterrolebinding" { - yaml_body = < v } - - policy_arn = each.value - role = aws_iam_role.cluster.name -} - -resource "aws_iam_role_policy_attachment" "cluster_additional" { - for_each = { for k, v in var.cluster_iam_role_additional_policies : k => v } - - policy_arn = each.value - role = aws_iam_role.cluster.name -} - -resource "aws_iam_role_policy_attachment" "cluster_encryption" { - # Encryption config not available on Outposts - count = var.create_encryption_kms_key ? 1 : 0 - - policy_arn = aws_iam_policy.cluster_encryption[0].arn - role = aws_iam_role.cluster.name -} - -resource "aws_iam_policy" "cluster_encryption" { - # Encryption config not available on Outposts - count = var.create_encryption_kms_key ? 1 : 0 - - name = local.cluster_encryption_policy_name - description = "EKS cluster encryption policy" - - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = [ - "kms:Encrypt", - "kms:Decrypt", - "kms:ListGrants", - "kms:DescribeKey", - ] - Effect = "Allow" - Resource = module.kms.key_arn - }, - ] - }) - - tags = var.tags -} diff --git a/modules/iam/datasources.tf b/modules/iam/datasources.tf deleted file mode 100644 index c5767b2..0000000 --- a/modules/iam/datasources.tf +++ /dev/null @@ -1,34 +0,0 @@ -data "aws_partition" "current" {} -data "aws_caller_identity" "current" {} - -data "aws_iam_session_context" "current" { - # This data source provides information on the IAM source role of an STS assumed role - # For non-role ARNs, this data source simply passes the ARN through issuer ARN - # Ref https://github.com/terraform-aws-modules/terraform-aws-eks/issues/2327#issuecomment-1355581682 - # Ref https://github.com/hashicorp/terraform-provider-aws/issues/28381 - arn = data.aws_caller_identity.current.arn -} - -data "aws_iam_policy_document" "cluster_assume_role_policy" { - statement { - sid = "EKSClusterAssumeRole" - actions = ["sts:AssumeRole"] - - principals { - type = "Service" - identifiers = ["eks.${data.aws_partition.current.dns_suffix}"] - } - } -} - -data "aws_iam_policy_document" "node_group_assume_role_policy" { - statement { - sid = "EKSNodeAssumeRole" - actions = ["sts:AssumeRole"] - - principals { - type = "Service" - identifiers = ["ec2.${data.aws_partition.current.dns_suffix}"] - } - } -} diff --git a/modules/iam/kms.tf b/modules/iam/kms.tf deleted file mode 100644 index c0b5f6b..0000000 --- a/modules/iam/kms.tf +++ /dev/null @@ -1,47 +0,0 @@ -################################################################################ -# KMS Key -################################################################################ - -module "kms" { - source = "terraform-aws-modules/kms/aws" - version = "1.1.0" # Note - be mindful of Terraform/provider version compatibility between modules - - create = var.create_encryption_kms_key - description = "${var.cluster_name} cluster encryption key used to encrypt resources, mainly k8s secrets" - key_usage = "ENCRYPT_DECRYPT" - deletion_window_in_days = 30 - enable_key_rotation = false - - # Policy - enable_default_policy = false - key_owners = [] - key_administrators = distinct(compact(concat( - [data.aws_iam_session_context.current.issuer_arn], # terraform role codeowner - var.kms_key_administrators, - ["arn:aws:iam::478986666586:role/TrackitMonitoringAdmin"], - ))) - key_users = [aws_iam_role.cluster.arn] - key_service_users = [] - source_policy_documents = [] - override_policy_documents = [] - - # Aliases - aliases = [] - computed_aliases = { - # Computed since users can pass in computed values for cluster name such as random provider resources - cluster = { - name = "service/${var.service}/eks/${var.env}/${var.cluster_name}" - } - } - - tags = merge( - { - component = "kms-eks-${var.cluster_name}" - service = var.service - Name = var.cluster_name - Environment = var.env - Creator = "Terraform" - }, - var.tags - ) -} diff --git a/modules/iam/locals.tf b/modules/iam/locals.tf deleted file mode 100644 index e471d67..0000000 --- a/modules/iam/locals.tf +++ /dev/null @@ -1,12 +0,0 @@ -locals { - role_name_prefix = "${var.cluster_name}-${var.env}-${var.aws_region_short}" - cluster_iam_role_name = "eks-${local.role_name_prefix}-cluster" - - cluster_encryption_policy_name = "eks-${local.role_name_prefix}-EKSClusterEncryption" - - node_group_iam_role_name = "eks-${local.role_name_prefix}-node" - - iam_role_policy_prefix = "arn:${data.aws_partition.current.partition}:iam::aws:policy" - - cni_policy = var.cluster_ip_family == "ipv6" ? "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/AmazonEKS_CNI_IPv6_Policy" : "${local.iam_role_policy_prefix}/AmazonEKS_CNI_Policy" -} diff --git a/modules/iam/main.tf b/modules/iam/main.tf new file mode 100644 index 0000000..952a143 --- /dev/null +++ b/modules/iam/main.tf @@ -0,0 +1,45 @@ +locals { + role_name = "eks-${var.cluster_name}" +} + +module "vpc_cni_irsa" { + source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" + version = "~> 5.39.1" + + role_name = "${local.role_name}-vpc-cni" + + attach_vpc_cni_policy = true + vpc_cni_enable_ipv4 = true + vpc_cni_enable_ipv6 = false + + oidc_providers = { + for idx, arn in var.cluster_oidc_provider_arns : + idx => { + provider_arn = arn + namespace_service_accounts = ["kube-system:aws-node"] + } + } + + tags = var.tags +} + +module "ebs_csi_irsa" { + source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks" + version = "~> 5.39.1" + + role_name = "${local.role_name}-ebs-csi" + + attach_ebs_csi_policy = true + + oidc_providers = { + for idx, arn in var.cluster_oidc_provider_arns : + idx => { + provider_arn = arn + namespace_service_accounts = [ + "kube-system:ebs-csi-controller-sa" + ] + } + } + + tags = var.tags +} diff --git a/modules/iam/node.tf b/modules/iam/node.tf deleted file mode 100644 index a2b53a7..0000000 --- a/modules/iam/node.tf +++ /dev/null @@ -1,33 +0,0 @@ -################################################################################ -# IAM Role -################################################################################ - -resource "aws_iam_role" "node_group" { - count = var.create_node_group_iam_role ? 1 : 0 - name = local.node_group_iam_role_name - description = "EKS Node Group IAM role" - - assume_role_policy = data.aws_iam_policy_document.node_group_assume_role_policy.json - force_detach_policies = true - - tags = var.tags -} - -# Policies attached ref https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group -resource "aws_iam_role_policy_attachment" "node_group" { - for_each = { for k, v in toset(compact([ - "${local.iam_role_policy_prefix}/AmazonEKSWorkerNodePolicy", - "${local.iam_role_policy_prefix}/AmazonEC2ContainerRegistryReadOnly", - local.cni_policy, - ])) : k => v if var.create_node_group_iam_role } - - policy_arn = each.value - role = aws_iam_role.node_group[0].name -} - -resource "aws_iam_role_policy_attachment" "node_group_additional" { - for_each = { for k, v in var.node_group_iam_role_additional_policies : k => v if var.create_node_group_iam_role } - - policy_arn = each.value - role = aws_iam_role.node_group[0].name -} diff --git a/modules/iam/outputs.tf b/modules/iam/outputs.tf index deae69a..fc5d9f2 100644 --- a/modules/iam/outputs.tf +++ b/modules/iam/outputs.tf @@ -1,24 +1,24 @@ -output "cluster_iam_role_arn" { - description = "Cluster IAM role ARN" - value = aws_iam_role.cluster.arn +output "vpc_cni_iam_role_arn" { + description = "ARN of IAM role for VPC CNI" + value = module.vpc_cni_irsa[0].iam_role_arn } -output "node_group_iam_role_arn" { - description = "Node Group IAM role ARN" - value = var.create_node_group_iam_role ? aws_iam_role.node_group[0].arn : null +output "vpc_cni_service_account_name" { + description = "Account name of IAM role for VPC CNI" + value = "${local.role_name}-vpc-cni" } -output "kms_key_arn" { - description = "The Amazon Resource Name (ARN) of the key" - value = var.create_encryption_kms_key ? module.kms.key_arn : null +output "iam_namespace" { + description = "Namespace for VPC CNI" + value = "kube-system" } -output "kms_key_id" { - description = "The globally unique identifier for the key" - value = var.create_encryption_kms_key ? module.kms.key_id : null +output "ebs_csi_iam_role_arn" { + description = "ARN of IAM role for EBS CSI" + value = module.ebs_csi_irsa[0].iam_role_arn } -output "kms_key_policy" { - description = "The IAM resource policy set on the key" - value = var.create_encryption_kms_key ? module.kms.key_policy : null +output "ebs_csi_service_account_name" { + description = "Account name of IAM role for EBS CSI" + value = "ebs-csi-controller-sa" } diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf index 3d5824a..8620827 100644 --- a/modules/iam/variables.tf +++ b/modules/iam/variables.tf @@ -1,69 +1,17 @@ -variable "cluster_name" { - description = "Name of the Cluster" - type = string -} - -variable "create_cloudwatch_log_group" { - description = "create cloudwatch log group" - type = bool - default = false -} - -variable "cluster_ip_family" { - description = "cluster IP family" - type = string - default = "ipv4" -} - -variable "cluster_iam_role_additional_policies" { - description = "cluster IAM role additional policies to attach" - type = map(string) - default = {} -} - -variable "create_node_group_iam_role" { - description = "Determines if an IAM role is created for the cluster node group" - type = bool - default = true -} - -variable "node_group_iam_role_additional_policies" { - description = "node group IAM role additional policies to attach" - type = map(string) - default = {} -} - -variable "create_encryption_kms_key" { - description = "create encryption kms key" - type = bool - default = true -} - variable "tags" { - description = "tags" + description = "Tags" type = map(string) - default = {} + default = { + "service" = "eks_terraform" + } } -variable "env" { - description = "environment" - type = string - default = "test" -} - -variable "service" { - description = "service name (team)" - type = string - default = "" -} - -variable "aws_region_short" { - description = "service name (team)" +variable "cluster_name" { + description = "EKS cluster name" type = string } -variable "kms_key_administrators" { - description = "kms key administrators list" +variable "cluster_oidc_provider_arns" { + description = "OIDC provider ARNs" type = list(string) - default = [] } diff --git a/route53.tf b/route53.tf index de095ce..dcce958 100644 --- a/route53.tf +++ b/route53.tf @@ -6,12 +6,7 @@ resource "aws_route53_zone" "private_zone" { vpc_id = var.network.vpc_id } - tags = { - Environment = var.env - Creator = "Terraform trackIt EKS module" - operator = "EKS" - component = "${var.cluster.name}.eks.${var.env}.${var.aws_region_short}.${var.zone_name}" - } + tags = var.tags } resource "aws_route53_record" "ns" { @@ -27,21 +22,3 @@ resource "aws_route53_record" "ns" { aws_route53_zone.private_zone.name_servers[3], ] } - -# resource "aws_route53_zone_association" "additional_vpcs" { -# zone_id = aws_route53_zone.private_zone.zone_id -# vpc_id = element( -# split( -# ",", -# element(var.private_hosted_zone_additional_vpc_ids_association, count.index), -# ), -# 0, -# ) -# vpc_region = element( -# split( -# ",", -# element(var.private_hosted_zone_additional_vpc_ids_association, count.index), -# ), -# 1, -# ) -# } From ae82e731b5ce0b176572331fe994294c572fba9f Mon Sep 17 00:00:00 2001 From: clementbolin Date: Sun, 15 Sep 2024 00:19:48 +0700 Subject: [PATCH 4/6] refactor: eks security groups --- datasources.tf | 8 ++++++++ eks.tf | 20 +++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 datasources.tf diff --git a/datasources.tf b/datasources.tf new file mode 100644 index 0000000..ef0ec45 --- /dev/null +++ b/datasources.tf @@ -0,0 +1,8 @@ +data "aws_vpc" "vpc" { + id = var.network.vpc_id +} + +data "aws_subnet" "selected" { + count = length(var.network.subnet_ids) + id = element(var.network.subnet_ids, count.index) +} diff --git a/eks.tf b/eks.tf index 74dfd91..243af3f 100644 --- a/eks.tf +++ b/eks.tf @@ -41,7 +41,25 @@ module "eks" { create_node_security_group = true node_security_group_additional_rules = var.node_security_group_additional_rules - cluster_security_group_additional_rules = var.cluster_security_group_additional_rules + cluster_security_group_additional_rules = merge( + { + eks_cluster = { + description = "Allow pods to communicate with the EKS cluster API Server" + from_port = 443 + to_port = 443 + protocol = "tcp" + security_group_id = module.eks.cluster_security_group_id + }, + k8s_api_to_current_vpc = { + description = "Allow the EKS cluster to communicate with the worker nodes" + from_port = 443 + to_port = 443 + protocol = "ingress" + security_group_id = [data.aws_vpc.vpc.cidr_block] + }, + }, + var.cluster_security_group_additional_rules + ) cluster_endpoint_public_access = var.cluster.endpoint_public_access || true cluster_endpoint_public_access_cidrs = var.endpoint_public_access_cidrs || ["0.0.0.0/0"] From 2ae0917eef7c58d309531a6ee6d45e6494f6baf2 Mon Sep 17 00:00:00 2001 From: clementbolin Date: Sun, 15 Sep 2024 00:49:14 +0700 Subject: [PATCH 5/6] refactor: karpenter configuration --- eks.tf | 171 ++++++++++++++++-------------- modules/karpenter/datasource.tf | 11 ++ modules/karpenter/main.tf | 84 +++++++++++++++ modules/karpenter/nodeTemplate.tf | 22 ---- modules/karpenter/provisioner.tf | 43 -------- modules/karpenter/variables.tf | 79 +++----------- variables.tf | 5 + 7 files changed, 202 insertions(+), 213 deletions(-) create mode 100644 modules/karpenter/datasource.tf create mode 100644 modules/karpenter/main.tf delete mode 100644 modules/karpenter/nodeTemplate.tf delete mode 100644 modules/karpenter/provisioner.tf diff --git a/eks.tf b/eks.tf index 243af3f..d95cde7 100644 --- a/eks.tf +++ b/eks.tf @@ -175,91 +175,98 @@ module "eks" { tags = var.tags } -resource "helm_release" "karpenter" { - namespace = "karpenter" - create_namespace = true - name = "karpenter" - repository = "oci://public.ecr.aws/karpenter" - repository_username = var.ecr_token.user_name - repository_password = var.ecr_token.password - chart = "karpenter" - version = "v0.34.0" - wait = false +module "karpenter" { + source = "./modules/karpenter" - values = [ - <<-EOT - settings: - clusterName: ${module.eks.cluster_name} - clusterEndpoint: ${module.eks.cluster_endpoint} - interruptionQueue: ${module.karpenter.queue_name} - serviceAccount: - annotations: - eks.amazonaws.com/role-arn: ${module.karpenter.iam_role_arn} - EOT - ] - - depends_on = [ - module.eks_auth, - module.karpenter - ] + cluster_name = module.eks.cluster_name + aws_region = var.aws_region } -resource "kubectl_manifest" "karpenter_node_class" { - yaml_body = <<-YAML - apiVersion: karpenter.k8s.aws/v1beta1 - kind: EC2NodeClass - metadata: - name: default - spec: - amiFamily: AL2 - role: ${module.karpenter.node_iam_role_name} - subnetSelectorTerms: - - tags: - karpenter.sh/discovery: ${module.eks.cluster_name} - securityGroupSelectorTerms: - - tags: - karpenter.sh/discovery: ${module.eks.cluster_name} - tags: - karpenter.sh/discovery: ${module.eks.cluster_name} - YAML +# resource "helm_release" "karpenter" { +# namespace = "karpenter" +# create_namespace = true +# name = "karpenter" +# repository = "oci://public.ecr.aws/karpenter" +# repository_username = var.ecr_token.user_name +# repository_password = var.ecr_token.password +# chart = "karpenter" +# version = "v0.34.0" +# wait = false - depends_on = [ - module.eks_auth - ] -} +# values = [ +# <<-EOT +# settings: +# clusterName: ${module.eks.cluster_name} +# clusterEndpoint: ${module.eks.cluster_endpoint} +# interruptionQueue: ${module.karpenter.queue_name} +# serviceAccount: +# annotations: +# eks.amazonaws.com/role-arn: ${module.karpenter.iam_role_arn} +# EOT +# ] -resource "kubectl_manifest" "karpenter_node_pool" { - yaml_body = <<-YAML - apiVersion: karpenter.sh/v1beta1 - kind: NodePool - metadata: - name: default - spec: - template: - spec: - nodeClassRef: - name: default - requirements: - - key: "karpenter.k8s.aws/instance-category" - operator: In - values: ["c", "m", "r"] - - key: "karpenter.k8s.aws/instance-cpu" - operator: In - values: ["4", "8", "16", "32"] - - key: "karpenter.k8s.aws/instance-hypervisor" - operator: In - values: ["nitro"] - - key: "karpenter.k8s.aws/instance-generation" - operator: Gt - values: ["2"] - limits: - cpu: 1000 - disruption: - consolidationPolicy: WhenEmpty - consolidateAfter: 30s - YAML +# depends_on = [ +# module.eks_auth, +# module.karpenter +# ] +# } - depends_on = [ - module.eks_auth - ] -} +# resource "kubectl_manifest" "karpenter_node_class" { +# yaml_body = <<-YAML +# apiVersion: karpenter.k8s.aws/v1beta1 +# kind: EC2NodeClass +# metadata: +# name: default +# spec: +# amiFamily: AL2 +# role: ${module.karpenter.node_iam_role_name} +# subnetSelectorTerms: +# - tags: +# karpenter.sh/discovery: ${module.eks.cluster_name} +# securityGroupSelectorTerms: +# - tags: +# karpenter.sh/discovery: ${module.eks.cluster_name} +# tags: +# karpenter.sh/discovery: ${module.eks.cluster_name} +# YAML + +# depends_on = [ +# module.eks_auth +# ] +# } + +# resource "kubectl_manifest" "karpenter_node_pool" { +# yaml_body = <<-YAML +# apiVersion: karpenter.sh/v1beta1 +# kind: NodePool +# metadata: +# name: default +# spec: +# template: +# spec: +# nodeClassRef: +# name: default +# requirements: +# - key: "karpenter.k8s.aws/instance-category" +# operator: In +# values: ["c", "m", "r"] +# - key: "karpenter.k8s.aws/instance-cpu" +# operator: In +# values: ["4", "8", "16", "32"] +# - key: "karpenter.k8s.aws/instance-hypervisor" +# operator: In +# values: ["nitro"] +# - key: "karpenter.k8s.aws/instance-generation" +# operator: Gt +# values: ["2"] +# limits: +# cpu: 1000 +# disruption: +# consolidationPolicy: WhenEmpty +# consolidateAfter: 30s +# YAML + +# depends_on = [ +# module.eks_auth +# ] +# } diff --git a/modules/karpenter/datasource.tf b/modules/karpenter/datasource.tf new file mode 100644 index 0000000..4ad0fe8 --- /dev/null +++ b/modules/karpenter/datasource.tf @@ -0,0 +1,11 @@ +data "aws_eks_cluster" "cluster" { + name = var.cluster_name +} + +data "aws_eks_cluster_auth" "cluster" { + name = var.cluster_name +} + +data "aws_iam_openid_connect_provider" "oidc_provider" { + url = data.aws_eks_cluster.cluster.identity[0].oidc.issuer +} diff --git a/modules/karpenter/main.tf b/modules/karpenter/main.tf new file mode 100644 index 0000000..55a6572 --- /dev/null +++ b/modules/karpenter/main.tf @@ -0,0 +1,84 @@ +module "eks_blueprints_addons" { + source = "aws-ia/eks-blueprints-addons/aws" + version = "~> 1.0.0" # Replace with the desired version + + cluster_name = var.cluster_name + cluster_endpoint = data.aws_eks_cluster.cluster.endpoint + cluster_version = data.aws_eks_cluster.cluster.version + oidc_provider_arn = data.aws_iam_openid_connect_provider.oidc_provider.arn + + karpenter = { + enable = true + version = "v1.0.0" # Specify the Karpenter version + namespace = "karpenter" # Namespace where Karpenter will be installed + } +} + +resource "kubectl_manifest" "ec2_node_class" { + yaml_body = try(var.ec2_node_class_yaml_body, <<-YAML + apiVersion: karpenter.k8s.aws/v1beta1 + kind: EC2NodeClass + metadata: + name: default + spec: + amiFamily: AL2 + role: ${module.eks_blueprints_addons.karpenter["node_iam_role_name"]} + subnetSelectorTerms: ${jsonencode(local.subnet_selector_terms)} + securityGroupSelectorTerms: + - tags: + karpenter.sh/discovery: ${var.cluster_name} + tags: + karpenter.sh/discovery: ${var.cluster_name} + YAML + ) + + depends_on = [ + module.eks_blueprints_addons + ] +} + +resource "kubectl_manifest" "node_pool" { + yaml_body = try(var.node_pool_yaml_body, <<-YAML + apiVersion: karpenter.sh/v1beta1 + kind: NodePool + metadata: + name: eks-addons + spec: + template: + spec: + nodeClassRef: + name: default + taints: + - key: eks-addons + effect: NoSchedule + requirements: + - key: "karpenter.k8s.aws/instance-generation" + operator: Gt + values: ["2"] + - key: "karpenter.k8s.aws/instance-memory" + operator: Gt + values: ["${try(var.node_pool_min_instance_memory - 1, "2047")}"] # 2 * 1024 - 1 + - key: "kubernetes.io/arch" + operator: In + values: ["arm64", "amd64"] + - key: "karpenter.sh/capacity-type" + operator: In + values: ["spot", "on-demand"] + - key: "karpenter.k8s.aws/instance-hypervisor" + operator: In + values: ["nitro"] # VPC CNI only supports instance types that run on the Nitro hypervisor + kubelet: + maxPods: 110 + limits: + cpu: "10" + disruption: + consolidationPolicy: WhenUnderutilized + expireAfter: 720h + YAML + ) + + depends_on = [ + module.eks_blueprints_addons, + kubectl_manifest.ec2_node_class + ] +} diff --git a/modules/karpenter/nodeTemplate.tf b/modules/karpenter/nodeTemplate.tf deleted file mode 100644 index a333e37..0000000 --- a/modules/karpenter/nodeTemplate.tf +++ /dev/null @@ -1,22 +0,0 @@ -resource "kubectl_manifest" "aws_node_template" { - count = var.create && var.create_kubernetes_resources && var.create_aws_node_template ? 1 : 0 - - yaml_body = try(var.aws_node_template.yaml_body, <<-YAML - apiVersion: karpenter.k8s.aws/v1alpha1 - kind: AWSNodeTemplate - metadata: - name: default - spec: - subnetSelector: - aws-ids: "${join(",", var.subnet_ids)}" - securityGroupSelector: - karpenter.sh/discovery: ${var.cluster_name} - tags: - karpenter.sh/discovery: ${var.cluster_name} - YAML - ) - - depends_on = [ - module.eks_blueprints_addons[0].karpenter - ] -} diff --git a/modules/karpenter/provisioner.tf b/modules/karpenter/provisioner.tf deleted file mode 100644 index c01d11a..0000000 --- a/modules/karpenter/provisioner.tf +++ /dev/null @@ -1,43 +0,0 @@ -resource "kubectl_manifest" "provisioner" { - count = var.create && var.create_kubernetes_resources && var.create_provisioner ? 1 : 0 - - yaml_body = try(var.provisioner.yaml_body, <<-YAML - apiVersion: karpenter.sh/v1alpha5 - kind: Provisioner - metadata: - name: ${var.cluster_name}-default - spec: - requirements: - - key: "topology.kubernetes.io/zone" - operator: In - values: ${jsonencode(var.availability_zones)} - - key: karpenter.k8s.aws/instance-category - operator: In - values: ["c", "m", "r"] - - key: karpenter.k8s.aws/instance-generation - operator: Gt - values: ["2"] - - key: kubernetes.io/arch - operator: In - values: ["arm64", "amd64"] - - key: "karpenter.sh/capacity-type" # If not included, the webhook for the AWS cloud provider will default to on-demand - operator: In - values: ["spot", "on-demand"] - kubeletConfiguration: - containerRuntime: containerd - maxPods: 110 - limits: - resources: - cpu: 1000 - consolidation: - enabled: true - providerRef: - name: default - ttlSecondsUntilExpired: 2592000 # 30 Days = 60 * 60 * 24 * 30 Seconds - YAML - ) - - depends_on = [ - module.eks_blueprints_addons[0].karpenter - ] -} \ No newline at end of file diff --git a/modules/karpenter/variables.tf b/modules/karpenter/variables.tf index aeaed76..29facb6 100644 --- a/modules/karpenter/variables.tf +++ b/modules/karpenter/variables.tf @@ -1,80 +1,27 @@ -variable "env" { - description = "Environnement where the stack is running" - type = string -} - -variable "service" { - description = "Service using this module" +variable "aws_region" { + description = "AWS Region where the EKS cluster is located" type = string } variable "cluster_name" { - description = "Name of the EKS cluster" - type = string -} - -variable "cluster_endpoint" { - description = "Endpoint for your Kubernetes API server" + description = "The name of the EKS cluster" type = string } -variable "cluster_version" { - description = "Kubernetes `.` version to use for the EKS cluster (i.e.: `1.24`)" +variable "ec2_node_class_yaml_body" { + description = "Optional custom YAML body for EC2 NodeClass" type = string + default = "" } -variable "oidc_provider_arn" { - description = "The ARN of the cluster OIDC Provider" +variable "node_pool_yaml_body" { + description = "Optional custom YAML body for NodePool" type = string + default = "" } -variable "create" { - description = "Controls if resources should be created (affects all resources)" - type = bool - default = true -} - -variable "karpenter" { - description = "Karpenter add-on configuration values" - type = any - default = {} -} - -variable "create_aws_node_template" { - type = bool - default = true -} - -variable "subnet_ids" { - type = list(string) -} - -variable "aws_node_template" { - type = any - default = {} -} - -variable "create_provisioner" { - type = bool - default = true -} - -variable "availability_zones" { - type = list(string) -} - -variable "provisioner" { - description = "Provisioner configuration values" - type = any - default = {} -} - -variable "create_delay_dependencies" { - type = list(string) - default = [] -} - -variable "create_kubernetes_resources" { - type = bool - default = true +variable "node_pool_min_instance_memory" { + description = "Minimum instance memory for NodePool in MiB" + type = number + default = 2048 # 2 * 1024 } diff --git a/variables.tf b/variables.tf index a214e82..208484d 100644 --- a/variables.tf +++ b/variables.tf @@ -49,6 +49,11 @@ variable "aws_region_short" { type = string } +variable "aws_region" { + description = "AWS region name" + type = string +} + variable "kms_key_administrators" { description = "KMS key administrators" type = list(string) From 0f3a28bcfc34a285a89926b14453bb2a38879988 Mon Sep 17 00:00:00 2001 From: clementbolin Date: Sun, 13 Oct 2024 22:37:42 +0200 Subject: [PATCH 6/6] chore: add example --- argocd.tf | 39 ++++ eks-addons.tf | 48 +++++ example/main.tf | 47 +++-- example/terraform.tfvars | 1 + example/variables.tf | 1 + modules/argocd/README.md | 44 +++++ modules/argocd/main.tf | 75 ++++++++ modules/argocd/variables.tf | 42 +++++ modules/argocd/versions.tf | 10 ++ modules/karpenter/providers.tf | 18 ++ modules/std_addons/datasources.tf | 1 + modules/std_addons/main.tf | 290 ++++++++++++++++++++++++++++++ modules/std_addons/outputs.tf | 39 ++++ modules/std_addons/variables.tf | 157 ++++++++++++++++ modules/std_addons/versions.tf | 18 ++ variables.tf | 106 +++++++++++ 16 files changed, 920 insertions(+), 16 deletions(-) create mode 100644 argocd.tf create mode 100644 eks-addons.tf create mode 100644 modules/argocd/README.md create mode 100644 modules/argocd/main.tf create mode 100644 modules/argocd/variables.tf create mode 100644 modules/argocd/versions.tf create mode 100644 modules/karpenter/providers.tf create mode 100644 modules/std_addons/datasources.tf create mode 100644 modules/std_addons/main.tf create mode 100644 modules/std_addons/outputs.tf create mode 100644 modules/std_addons/variables.tf create mode 100644 modules/std_addons/versions.tf diff --git a/argocd.tf b/argocd.tf new file mode 100644 index 0000000..f596e56 --- /dev/null +++ b/argocd.tf @@ -0,0 +1,39 @@ +module "argocd" { + source = "./modules/argocd" + + env = "staging" + aws_region = var.aws_region + + cluster = { + name = module.eks.cluster_name + endpoint = module.eks.cluster_endpoint + version = module.eks.cluster_version + oidc_provider_arn = module.eks.oidc.provider_arn + } + + argocd = { + name = "argocd" + namespace = "argocd" + chart_version = "5.29.1" + + hostname = "argocd-${module.eks.cluster_name}-cluster-${var.tags.env}.stg.anidn.fr" + + gitlab_app_id = "id" + gitlab_app_installation_id = "id" + gitlab_app_private_key = "key" + + rbac_policy_default = "role:readonly" + rbac_policy_csv = <<-EOF +g, innov-ft:infra, role:admin +EOF + + bootstrap_url = "https://gitlab.com/VizMediaEurope/adn-eks-apps.git" + bootstrap_path = "staging/services/*" + } + + argocd_ingress_scheme = "internet-facing" + + depends_on = [ + module.std_addons, + ] +} diff --git a/eks-addons.tf b/eks-addons.tf new file mode 100644 index 0000000..03f3382 --- /dev/null +++ b/eks-addons.tf @@ -0,0 +1,48 @@ +module "std_addons" { + source = "./modules/std_addons" + + env = var.env + aws_region = var.aws_region + service = var.service + tags = var.tags + + cluster_endpoint = module.eks.cluster_endpoint + cluster_version = module.eks.cluster_version + oidc_provider_arn = module.eks.oidc_provider_arn + + cluster_name = module.eks.cluster_name + + enable_ebs_csi = var.enable_ebs_csi + ebs_csi = merge( + { + iam_role_arn = module.irsa.ebs_csi_iam_role_arn + }, var.ebs_csi, + ) + + # We want to wait for Karpenter and coredns to be deployed first + create_delay_dependencies = compact(concat( + [module.karpenter.delay_dependency], + try([module.eks.cluster_addons["coredns"]["name"]], []), + [module.observability.prometheus_crds_dependency], + )) + + enable_external_dns = var.enable_external_dns + external_dns = merge( + var.external_dns, + # Avoid DNS record creation for nginx-ingress as it does not expose external IP address + can(var.ingress_nginx_alb.target_group_arn) ? { + extra_args = concat(["--ingress-class=alb"], try(var.external_dns.extra_args, [])) + } : {} + ) + hosted_zones = concat( + module.private_zone.zone, + [for v in data.aws_route53_zone.argocd : { name = v.name, zone_id = v.zone_id, arn = v.arn }], + [for v in data.aws_route53_zone.additional : { name = v.name, zone_id = v.zone_id, arn = v.arn }], + ) + + enable_external_secrets = var.enable_external_secrets + external_secrets = var.external_secrets + + enable_aws_load_balancer_controller = var.enable_aws_load_balancer_controller + aws_load_balancer_controller = var.aws_load_balancer_controller +} diff --git a/example/main.tf b/example/main.tf index 79f3749..7725b8d 100644 --- a/example/main.tf +++ b/example/main.tf @@ -1,35 +1,50 @@ +locals { + service = "infra" +} + +data "aws_caller_identity" "current" {} + module "eks" { - source = "./../" + source = "../" + aws_region = var.aws_region aws_region_short = var.aws_region_short + env = var.tags.env - network = { - vpc_id = local.vpc_id - subnet_ids = var.vpc.subnet_ids - control_plane_subnet_ids = var.vpc.subnet_ids + cluster = { + name = var.cluster_name + version = "1.30" + endpoint_public_access = true + endpoint_public_access_cidrs = [] } - cluster = { - version = "1.29" - name = var.cluster_name - endpoint_public_access = false + network = { + vpc_id = var.vpc.id + subnet_ids = var.vpc.private_subnets + control_plane_subnet_ids = var.vpc.private_subnets } - kms_key_administrators = [ - "arn:aws:iam::XXXXXXXX:user/trackit-eks", - ] + auth = { + admin_role_arns = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/eks-admin"] + kms_key_administrators = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } ecr_token = { - password = data.aws_ecrpublic_authorization_token.token.password - user_name = data.aws_ecrpublic_authorization_token.token.user_name + user_name = "terraform" + password = "password" } - env = "staging" - zone_name = "XXXX.tech" + kms_key_administrators = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + aws_auth_role_arns = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/eks-admin"] + + service = abs(local.service) + + zone_name = "stg.anidn.fr" tags = var.tags } + resource "kubectl_manifest" "karpenter_node_class" { yaml_body = <<-YAML apiVersion: karpenter.k8s.aws/v1beta1 diff --git a/example/terraform.tfvars b/example/terraform.tfvars index 72a9fb7..f28b697 100644 --- a/example/terraform.tfvars +++ b/example/terraform.tfvars @@ -1,6 +1,7 @@ aws_region = "eu-west-3" vpc = { + id = "value" name = "trackit-vpc" cidr = "10.0.0.0/16" azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"] diff --git a/example/variables.tf b/example/variables.tf index a05199d..a7eca53 100644 --- a/example/variables.tf +++ b/example/variables.tf @@ -1,6 +1,7 @@ variable "vpc" { description = "The VPC custom configuration" type = object({ + id = string name = string cidr = string azs = list(string) diff --git a/modules/argocd/README.md b/modules/argocd/README.md new file mode 100644 index 0000000..c3c25a7 --- /dev/null +++ b/modules/argocd/README.md @@ -0,0 +1,44 @@ +# ArgoCD module + +This module will install ArgoCD helm chart + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [kubectl](#requirement\_kubectl) | >= 1.10.0 | + +## Providers + +| Name | Version | +|------|---------| +| [kubectl](#provider\_kubectl) | >= 1.10.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [this](#module\_this) | aws-ia/eks-blueprints-addon/aws | 1.0.0 | + +## Resources + +| Name | Type | +|------|------| +| [kubectl_manifest.applicationset_bootstrap](https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs/resources/manifest) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [argocd](#input\_argocd) | ArgoCD related values | `any` | n/a | yes | +| [argocd\_ingress\_scheme](#input\_argocd\_ingress\_scheme) | ArgoCD ingress scheme | `string` | `"internal"` | no | +| [aws\_region](#input\_aws\_region) | AWS region | `string` | n/a | yes | +| [cluster\_name](#input\_cluster\_name) | EKS cluster name | `string` | n/a | yes | +| [env](#input\_env) | environment | `string` | n/a | yes | + +## Outputs + +No outputs. + diff --git a/modules/argocd/main.tf b/modules/argocd/main.tf new file mode 100644 index 0000000..73a0273 --- /dev/null +++ b/modules/argocd/main.tf @@ -0,0 +1,75 @@ +resource "kubernetes_namespace" "argocd" { + metadata { + name = "argocd" + } + + depends_on = [module.eks] +} + +module "eks-blueprints-addons-argocd" { + source = "aws-ia/eks-blueprints-addons/aws" + version = "~> 1.0" + + cluster_name = var.cluster.name + cluster_endpoint = var.cluster.endpoint + cluster_version = var.cluster.version + oidc_provider_arn = var.cluster.oidc_provider_arn + + enable_argocd = true + + argocd = { + name = "argocd" + chart_version = "5.42.2" + repository = "https://argoproj.github.io/argo-helm" + namespace = "argocd" + values = [ + <