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}