EKS AWS Managed NodeGroups

Creating a EKS Cluster with AWS-Managed Node Groups

USE CASE: Create All Necessory Infrastructure for EKS Managed Kubernetes Cluster with Terraform.

Creating an Amazon EKS (Elastic Kubernetes Service) cluster can be streamlined using Terraform. Below is a comprehensive example of how to set up an EKS cluster along with necessary configurations for logging, IAM roles, and access entries.

Terraform Code

Here's how to create an EKS cluster with essential configurations:

 1data "tls_certificate" "demo" {
 2  count = var.ENVIRONMENT != "PROD" ? 1 : 0
 3  url = aws_eks_cluster.eks.identity.0.oidc.0.issuer
 4}
 5
 6data "aws_caller_identity" "current" {}
 7data "aws_region" "current" {}
 8
 9resource "aws_iam_openid_connect_provider" "demo" {
10  count = var.ENVIRONMENT != "PROD" ? 1 : 0
11  client_id_list = ["sts.amazonaws.com"]
12  thumbprint_list = [data.tls_certificate.demo[count.index].certificates[0].sha1_fingerprint]
13  url = aws_eks_cluster.eks.identity.0.oidc.0.issuer
14}
15
16resource "aws_cloudwatch_log_group" "cluster-logs" {
17  name = "${var.CLUSTER_NAME}-Log-Group"
18  retention_in_days = var.LOGS_RETENTION_IN_DAYS
19
20  tags = {
21    Name = "${var.CLUSTER_NAME}-Log-Group"
22  }
23}
24
25resource "aws_eks_cluster" "eks" {
26  name     = var.CLUSTER_NAME
27  version  = var.KUBERNETES_VERSION
28  role_arn = var.CLUSTER_ROLE_ARN
29  enabled_cluster_log_types = var.LOGGING_TYPE
30
31  encryption_config {
32    resources = ["secrets"]
33    provider {
34      key_arn = var.KMS_ARN
35    }
36  }
37
38  access_config {
39    authentication_mode = var.ACCESS_CONFIG
40    bootstrap_cluster_creator_admin_permissions = false
41  }
42
43  vpc_config {
44    security_group_ids = var.SECURITY_GROUP_ID_CLUSTER
45    subnet_ids         = var.CLUSTER_SUBNET_IDS
46    endpoint_private_access = var.ENDPOINT_PRIVATE_ACCESS
47    endpoint_public_access  = var.ENDPOINT_PUBLIC_ACCESS
48    public_access_cidrs     = var.PUBLIC_ACCESS_CIDRS
49  }
50
51  tags = merge(
52    var.COMMON_TAGS,
53    var.TAGS,
54    {
55      "Name" = var.CLUSTER_NAME
56    },
57    {
58      "kubernetes.io/cluster/${var.CLUSTER_NAME}" = "owned"
59    }
60  )
61}

Creating AWS Managed Node Groups with Terraform

AWS Managed Node Groups simplify the management of worker nodes in your Amazon EKS (Elastic Kubernetes Service) cluster. This guide demonstrates how to create an AWS managed node group using Terraform.

Terraform Code

Below is Terraform configuration for creating a managed node group named backend-node-group:

 1resource "aws_eks_node_group" "backend_node_group" {
 2  depends_on = [ aws_eks_cluster.eks]
 3
 4  cluster_name    = var.CLUSTER_NAME
 5  node_group_name = "backend-node-group"
 6  node_role_arn   = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/EKS_NodeGroup_Role"
 7
 8  subnet_ids = var.CLUSTER_SUBNET_IDS  # Specify your subnet IDs
 9  
10  capacity_type = var.CAPACITY_TYPE  # On-Demand or Spot Instances
11  scaling_config {
12    desired_size = var.BACKEND_DESIRED_SIZE  # Desired number of nodes
13    max_size     = var.BACKEND_MAX_SIZE      # Maximum number of nodes
14    min_size     = var.BACKEND_MIN_SIZE      # Minimum number of nodes
15  }
16
17  taint {
18    key    = "requestor"
19    value  = "backend"
20    effect = "NO_EXECUTE"  # Prevents pods that do not tolerate this taint from being scheduled on the nodes
21  }
22
23    launch_template {
24      name    = aws_launch_template.backend_launch_template.name
25      version = aws_launch_template.backend_launch_template.latest_version
26    }
27
28  labels = {
29    wazuh   = true
30    backend = true
31    datadog = true
32  }
33
34  instance_types = var.INSTANCE_TYPES  # Specify your desired instance type(s)
35}

Access Entries and Policies

Access to the EKS cluster can be managed through IAM roles and Kubernetes RBAC. The following resources define access entries for Admin role:

 1resource "aws_eks_access_entry" "admin" {
 2  depends_on = [ aws_eks_cluster.eks]
 3  cluster_name      = var.CLUSTER_NAME
 4  principal_arn     = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-reserved/sso.amazonaws.com/${var.ADMIN_SSO_ROLE}"
 5  kubernetes_groups = ["admin"]
 6  type              = "STANDARD"
 7}
 8
 9# Similar blocks for devops, oidc_infra, and oidc roles...
10
11resource "aws_eks_access_policy_association" "admin" {
12  depends_on = [aws_eks_access_entry.admin]
13  cluster_name  = var.CLUSTER_NAME
14  policy_arn    = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy"
15  principal_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/aws-reserved/sso.amazonaws.com/${var.ADMIN_SSO_ROLE}"
16
17  access_scope {
18    type = "cluster"
19  }
20}

Calling the Module

Finally, I call the module with specific parameters, including the instance types, cluster name, desired capacity, and more.

 1module "EKS" {
 2
 3  source      = "../../modules/EKS"
 4  TAGS        = var.TAGS
 5  COMMON_TAGS = local.common_tags
 6
 7  ###########################
 8  ##### Control Plane Logging
 9  LOGS_RETENTION_IN_DAYS = var.LOGS_RETENTION_IN_DAYS
10
11  ##########################
12  ############## EKS Cluster
13  ENVIRONMENT                  = "DEV"
14  CLUSTER_NAME                 = "dev-eks"
15  KUBERNETES_VERSION           = "1.30"
16  ACCESS_CONFIG                = "API_AND_CONFIG_MAP"
17  CLUSTER_ROLE_ARN             = module.IAM_Role_cluster.IAM_ROLE_ARN_FOR_STATEMENT
18  ENDPOINT_PUBLIC_ACCESS       = var.ENDPOINT_PUBLIC_ACCESS
19  PUBLIC_ACCESS_CIDRS          = var.PUBLIC_ACCESS_CIDRS
20  ENDPOINT_PRIVATE_ACCESS      = var.ENDPOINT_PRIVATE_ACCESS
21  LOGGING_TYPE                 = ["api", "audit", "authenticator", "controllerManager", "scheduler"]
22  KMS_ARN                      = data.terraform_remote_state.kms_iam_sg.outputs.EKS_KMS_KEY_ARN
23  SECURITY_GROUP_IDS           = ["${data.terraform_remote_state.kms_iam_sg.outputs.EKS_SECURITY_GROUP_ID}"]
24  CLUSTER_SUBNET_IDS           = data.terraform_remote_state.vpc.outputs.PUBLIC_SUBNET_IDS
25  INSTANCE_TYPES               = ["t3a.medium","t3.medium","t2.medium"]
26  CAPACITY_TYPE                = "SPOT"
27  BACKEND_MAX_SIZE             = 45
28  BACKEND_DESIRED_SIZE         = 35
29  BACKEND_MIN_SIZE             = 25
30  CODEBUILD_ROLE               = "xxxxxxxxxxxxxxxxx-AdministratorAccess"
31  ADMIN_SSO_ROLE               = "AWSReservedSSO_Admin_xxxxxxxxxxxxxxxx"
32  DEVOPS_SSO_ROLE              = "AWSReservedSSO_Devops_xxxxxxxxxxxxxxx"
33  FULLACCESS_SSO_ROLE          = ""
34  READACCESS_SSO_ROLE          = ""
35  GITHUB_OIDC_ROLE             = "githubactions_oidc"
36  VPC_ID                       = data.terraform_remote_state.vpc.outputs.VPC_ID
37  INGRESS_ROLE_ARN             = module.IAM_Role.IAM_ROLE_ARN
38}