In this blog, we’ll explore how to create an EKS cluster using a Terraform module, including setting up a node group, , ECR, ACM, and other core components.
Amazon EKS (Elastic Kubernetes Service) provides a managed Kubernetes service that makes it easy to run Kubernetes on AWS without needing to manage your own control plane.
GIT LINK: https://github.com/ravindrasinghh/Kubernetes-Playlist
Prerequisites
Before you begin, ensure that you have the following tools installed:
- Terraform: Install Terraform by following the official installation guide.
- AWS CLI: Install and configure the AWS CLI by following the AWS CLI installation guide.
- kubectl: Install kubectl for interacting with your EKS cluster by following the kubectl installation guide.
Let’s Begin😎
👉🏻** What are Terraform modules?**
A Terraform module is a set of organized configuration files within a specific directory. These modules bundle together resources focused on a particular task, helping to minimize the amount of code you need to write for similar infrastructure components.
Here is the structure for that.
Step1: Clone the Repository
🧑🏻💻git clone https://github.com/ravindrasinghh/Kubernetes-Playlist.git
👨🏻💻cd Kubernetes-Playlist/Lesson1/
Step 2: Initialize Terraform
terraform init
terraform plan
terraform apply
👉🏻acm.tf
module "acm_backend" { source = "terraform-aws-modules/acm/aws" version = "4.0.1" domain_name = "codedevops.cloud" subject_alternative_names = [ "*.codedevops.cloud" ] zone_id = data.aws_route53_zone.main.id validation_method = "DNS" wait_for_validation = true tags = { Name = "${local.project}-${local.env}-backend-validation" } } data "aws_route53_zone" "main" { name = "codedevops.cloud." # Ensure the domain name ends with a dot }
👉🏻data.tf
data "aws_caller_identity" "current" {}
👉🏻ecr.tf
resource "aws_ecr_repository" "foo" { for_each = toset(local.ecr_names) name = each.key image_tag_mutability = "MUTABLE" tags = { Name = "${local.project}-${local.env}-ecr" } }
👉🏻eks.tf
module "eks" { source = "terraform-aws-modules/eks/aws" version = "20.13.1" cluster_name = local.cluster_name cluster_version = local.cluster_version cluster_enabled_log_types = local.cluster_enabled_log_types cloudwatch_log_group_retention_in_days = 30 cluster_endpoint_public_access = true cluster_addons = { coredns = { most_recent = true resolve_conflicts_on_create = "OVERWRITE" configuration_values = jsonencode(local.coredns_config) } kube-proxy = { most_recent = true } vpc-cni = { most_recent = true service_account_role_arn = aws_iam_role.vpc_cni.arn } } vpc_id = local.vpc_id subnet_ids = local.public_subnet_ids eks_managed_node_group_defaults = { ## This instance type (m6a.large) is a placeholder and will not be used in the actual deployment. } eks_managed_node_groups = local.eks_managed_node_groups cluster_security_group_additional_rules = local.cluster_security_group_additional_rules enable_cluster_creator_admin_permissions = false access_entries = { for k in local.eks_access_entries : k.username => { kubernetes_groups = [] principal_arn = k.username policy_associations = { single = { policy_arn = k.access_policy access_scope = { type = "cluster" } } } } } tags = local.default_tags } #Role for vpc cni resource "aws_iam_role" "vpc_cni" { name = "${local.prefix}-vpc-cni" assume_role_policy = <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "${module.eks.oidc_provider_arn}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${module.eks.oidc_provider}:sub": "system:serviceaccount:kube-system:aws-node" } } } ] } EOF } resource "aws_iam_role_policy_attachment" "vpc_cni" { role = aws_iam_role.vpc_cni.name policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" }
👉🏻locals.tf
data "aws_eks_cluster_auth" "eks" { name = module.eks.cluster_name } locals { environment = terraform.workspace k8s_info = lookup(var.environments, local.environment) cluster_name = lookup(local.k8s_info, "cluster_name") region = lookup(local.k8s_info, "region") env = lookup(local.k8s_info, "env") vpc_id = lookup(local.k8s_info, "vpc_id") vpc_cidr = lookup(local.k8s_info, "vpc_cidr") public_subnet_ids = lookup(local.k8s_info, "public_subnet_ids") cluster_version = lookup(local.k8s_info, "cluster_version") cluster_enabled_log_types = lookup(local.k8s_info, "cluster_enabled_log_types") eks_managed_node_groups = lookup(local.k8s_info, "eks_managed_node_groups") cluster_security_group_additional_rules = lookup(local.k8s_info, "cluster_security_group_additional_rules") coredns_config = lookup(local.k8s_info, "coredns_config") ecr_names = lookup(local.k8s_info, "ecr_names") prefix = "${local.project}-${local.environment}-${var.region}" eks_access_entries = flatten([for k, v in local.k8s_info.eks_access_entries : [for s in v.user_arn : { username = s, access_policy = lookup(local.eks_access_policy, k), group = k }]]) eks_access_policy = { viewer = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy", admin = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy" } project = "codedevops" account_id = data.aws_caller_identity.current.account_id default_tags = { environment = local.environment managed_by = "terraform" project = local.project } }
👉🏻output.tf
output "cluster_name" { value = module.eks.cluster_name description = "The name of the created EKS cluster." } output "cluster_version" { value = module.eks.cluster_version description = "The version of Kubernetes running on the EKS cluster." } output "cluster_endpoint" { value = module.eks.cluster_endpoint description = "The endpoint for the EKS Kubernetes API server." } output "access_entries" { value = module.eks.access_entries } output "oidc_provider" { value = module.eks.oidc_provider } output "oidc_provider_arn" { value = module.eks.oidc_provider_arn } output "acm_certificate_arn" { value = module.acm_backend.acm_certificate_arn }
👉🏻provider.tf
terraform { backend "s3" { bucket = "devsecops-backend-codedevops" key = "secops-dev.tfstae" region = "ap-south-1" } } terraform { required_version = ">= 0.15.0" required_providers { aws = { source = "hashicorp/aws" version = ">= 4.29.0" } random = { source = "hashicorp/random" version = ">= 3.6.0" } template = { source = "hashicorp/template" version = ">= 2.2.0" } } } provider "aws" { region = var.region allowed_account_ids = [434605749312] default_tags { tags = local.default_tags } } provider "kubernetes" { host = module.eks.cluster_endpoint cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) token = data.aws_eks_cluster_auth.eks.token } provider "helm" { kubernetes { host = module.eks.cluster_endpoint cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) token = data.aws_eks_cluster_auth.eks.token } }
👉🏻terraform.tfvars
environments = { default = { # Global variables cluster_name = "codedevops-cluster" env = "default" region = "ap-south-1" vpc_id = "vpc-02af529e05c41b6bb" vpc_cidr = "10.0.0.0/16" public_subnet_ids = ["subnet-09aeb297a112767b2", "subnet-0e25e76fb4326ce99"] cluster_version = "1.29" cluster_endpoint_public_access = true ecr_names = ["codedevops"] # EKS variables eks_managed_node_groups = { generalworkload-v4 = { min_size = 1 max_size = 1 desired_size = 1 instance_types = ["m5a.xlarge"] capacity_type = "SPOT" disk_size = 60 ebs_optimized = true iam_role_additional_policies = { ssm_access = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" cloudwatch_access = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" service_role_ssm = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM" default_policy = "arn:aws:iam::aws:policy/AmazonSSMManagedEC2InstanceDefaultPolicy" } } } cluster_security_group_additional_rules = {} # EKS Cluster Logging cluster_enabled_log_types = ["audit"] eks_access_entries = { viewer = { user_arn = [] } admin = { user_arn = ["arn:aws:iam::434605749312:root"] } } # EKS Addons variables coredns_config = { replicaCount = 1 } } }
👉🏻variables.tf
variable "region" { type = any default = "ap-south-1" description = "value of the region where the resources will be created" } variable "environments" { type = any description = "The environment configuration" }
Step 3: Access Your EKS Cluster
Once the cluster is created, you can configure kubectl to interact with your EKS cluster using the following command:
aws eks --region update-kubeconfig --name
You can then verify the cluster connectivity:
kubectl get nodes
Troubleshooting
If you encounter any issues, refer to the Terraform documentation or raise an issue in this repository.
🏴☠️
source link: https://github.com/ravindrasinghh/Kubernetes-Playlist/tree/master
If you prefer a video tutorial to help guide you to create the EKS Cluster Using Terraform
Top comments (0)