<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Terraform blog]]></title><description><![CDATA[Terraform blog]]></description><link>https://terraformfordevops.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 10:27:09 GMT</lastBuildDate><atom:link href="https://terraformfordevops.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Set Up a Kubernetes Cluster on AWS EKS Using Terraform.]]></title><description><![CDATA[Introduction
🔶In this blog, I’ll walk you through how to set up a Kubernetes cluster on AWS using Terraform. By combining the power of Infrastructure as Code (IaC) with AWS’s managed Kubernetes service (EKS), we can automate the provisioning of a sc...]]></description><link>https://terraformfordevops.hashnode.dev/how-to-set-up-a-kubernetes-cluster-on-aws-eks-using-terraform</link><guid isPermaLink="true">https://terraformfordevops.hashnode.dev/how-to-set-up-a-kubernetes-cluster-on-aws-eks-using-terraform</guid><category><![CDATA[AWS]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[ip address]]></category><dc:creator><![CDATA[VIKRANT SARADE]]></dc:creator><pubDate>Wed, 16 Apr 2025 17:27:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744826406338/61cd040c-ecfe-4c9c-88f9-0fa753d566da.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744820819029/52d1766e-8ac0-4feb-ab54-926ee78a5cb7.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-introduction">Introduction</h2>
<p>🔶In this blog, I’ll walk you through how to set up a Kubernetes cluster on AWS using Terraform. By combining the power of Infrastructure as Code (IaC) with AWS’s managed Kubernetes service (EKS), we can automate the provisioning of a scalable and production-ready cluster with ease.</p>
<p>The Terraform script I’ve shared takes care of creating all the necessary AWS resources—VPC, subnets, IAM roles, security groups, and the EKS cluster itself—allowing you to spin up your environment reliably and consistently with just a few commands.</p>
<p>Whether you're a DevOps enthusiast or a developer exploring Kubernetes deployment, this guide will help you understand the process from start to finish.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before diving in, make sure you're familiar with the following:</p>
<ul>
<li><p>✅ <strong>AWS Console</strong> – Basic understanding of navigating and managing services in the AWS Management Console.</p>
</li>
<li><p>✅ <strong>Terraform Scripting</strong> – Ability to write and understand Terraform configurations (HCL).</p>
</li>
<li><p>✅ <strong>VS Code</strong> – Experience using Visual Studio Code or any preferred code editor.</p>
</li>
<li><p>✅ <strong>Kubernetes Concepts</strong> – Familiarity with core Kubernetes components like pods, nodes, deployments, and services.  </p>
</li>
</ul>
<h3 id="heading-why-do-we-need-kubernetes">Why Do We Need Kubernetes?</h3>
<p>As applications grow in complexity and scale, managing containers manually becomes inefficient and error-prone. Kubernetes, an open-source container orchestration platform, addresses these challenges by automating deployment, scaling, and management of containerized applications.</p>
<p><strong>Key reasons we need Kubernetes:</strong></p>
<ul>
<li><p><strong>Automated Deployment &amp; Scaling:</strong> Kubernetes handles the rollout and scaling of containerized applications automatically based on demand.</p>
</li>
<li><p><strong>Self-healing:</strong> If a container crashes, Kubernetes replaces it instantly without human intervention.</p>
</li>
<li><p><strong>Load Balancing:</strong> It efficiently distributes network traffic to maintain stable performance.</p>
</li>
<li><p><strong>Service Discovery:</strong> Kubernetes automatically assigns IPs and DNS names to containers for seamless communication.</p>
</li>
<li><p><strong>Resource Optimization:</strong> It intelligently schedules containers to make the most of your infrastructure.</p>
</li>
</ul>
<blockquote>
<p><mark>In this project, we are going to use </mark> <strong><mark>AWS EKS,</mark></strong> <mark> which will serve as the crucial control plane for us.</mark>  </p>
</blockquote>
<h3 id="heading-extra-knowledge">💡Extra Knowledge</h3>
<h3 id="heading-how-to-write-an-ip-address">✅ How to Write an IP Address</h3>
<p>An <strong>IPv4</strong> address (the common one) looks like this:</p>
<pre><code class="lang-bash">192.168.1.1
</code></pre>
<p>It’s made up of <strong>4 numbers</strong>, separated by <strong>dots</strong>. Each number is called an <strong>octet</strong> or <strong>block</strong>.</p>
<hr />
<h3 id="heading-whats-in-each-block">✅ What’s in Each Block?</h3>
<p>Each block:</p>
<ul>
<li><p>Is a number from <strong>0 to 255</strong></p>
</li>
<li><p>Represents <strong>8 bits</strong> (since 1 byte = 8 bits, and 8 bits can represent numbers from 0 to 255)</p>
</li>
</ul>
<p>So the full IP has <strong>4 blocks × 8 bits = 32 bits total</strong></p>
<h4 id="heading-example">Example:</h4>
<pre><code class="lang-bash"> IP:  192 . 168 .   1 .  1
        ↑     ↑     ↑     ↑
      block block block block
</code></pre>
<h2 id="heading-lets-get-started">Let’s get started</h2>
<h3 id="heading-project-structure-and-file-overview">🔹Project Structure and File Overview</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744823255638/967c4b67-c314-4186-8fe9-824dcb84b6da.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p>To keep the configuration modular and maintainable, I’ve structured the Terraform project using multiple <code>.tf</code> files, each serving a specific purpose:</p>
<ul>
<li><p><code>terraform.tf</code><br />  This file contains the basic Terraform configuration, such as the required version and the backend (if configured). It acts as the entry point for initializing and managing the Terraform project.</p>
</li>
<li><p><code>providers.tf</code><br />  Here, I define the AWS provider configuration, including the region and access credentials. This tells Terraform which cloud platform to use and how to authenticate.</p>
</li>
<li><p><code>eks.tf</code> <em>(Main Configuration)</em><br />  This is the heart of the project. It contains all the resources needed to provision the AWS EKS (Elastic Kubernetes Service) cluster — including the cluster itself, node groups, IAM roles, and relevant associations.</p>
</li>
<li><p><code>locals.tf</code><br />  This file is used to define <strong>local variables</strong> that are reused across the project. It helps to avoid repetition and keep values consistent (like region names, tags, or naming conventions).</p>
</li>
<li><p><code>vpc.tf</code><br />  The VPC configuration file is crucial for setting up a <strong>custom Virtual Private Cloud</strong>, including subnets, internet gateways, and route tables. This ensures that all EKS nodes stay connected and operate within the same secure network boundary.  </p>
</li>
</ul>
</li>
</ol>
<p><strong>terraform.tf</strong></p>
<pre><code class="lang-bash">terraform{
    required_providers {
        aws = {
            <span class="hljs-built_in">source</span>  = <span class="hljs-string">"hashicorp/aws"</span>
            version = <span class="hljs-string">"5.93.0"</span>
        }
    }
}
</code></pre>
<p><strong>providers.tf</strong></p>
<pre><code class="lang-bash">provider <span class="hljs-string">"aws"</span> {
  region = local.region

}
</code></pre>
<p><strong>locals.tf</strong></p>
<pre><code class="lang-bash">locals{
    region = <span class="hljs-string">"us-east-1"</span>
    name = <span class="hljs-string">"my-eks-cluster"</span> <span class="hljs-comment"># EKS Cluster name</span>
    azs             = [<span class="hljs-string">"us-east-1a"</span>, <span class="hljs-string">"us-east-1b"</span>]
    private_subnets = [<span class="hljs-string">"10.0.1.0/24"</span>, <span class="hljs-string">"10.0.2.0/24"</span>]
    public_subnets  = [<span class="hljs-string">"10.0.101.0/24"</span>, <span class="hljs-string">"10.0.102.0/24"</span>]
    intra_subnets  = [<span class="hljs-string">"10.0.5.0/24"</span>, <span class="hljs-string">"10.0.6.0/24"</span>]

    env=<span class="hljs-string">"dev"</span> <span class="hljs-comment"># Environment name</span>

    }
</code></pre>
<p><strong>vpc.tf</strong></p>
<pre><code class="lang-bash">module <span class="hljs-string">"vpc"</span> {
  <span class="hljs-built_in">source</span> = <span class="hljs-string">"terraform-aws-modules/vpc/aws"</span>

  name = <span class="hljs-string">"first-eks-cluster-vpc"</span>
  cidr = <span class="hljs-string">"10.0.0.0/16"</span>

  azs             = local.azs
  private_subnets = local.private_subnets
  public_subnets  = local.public_subnets
  intra_subnets   = local.intra_subnets


  enable_nat_gateway = <span class="hljs-literal">true</span>
  enable_vpn_gateway = <span class="hljs-literal">true</span>

  tags = {
    Terraform = <span class="hljs-string">"true"</span>
    Environment = local.env
  }
}
</code></pre>
<p><strong>eks.tf</strong></p>
<pre><code class="lang-bash">module <span class="hljs-string">"eks"</span> {
  <span class="hljs-built_in">source</span>  = <span class="hljs-string">"terraform-aws-modules/eks/aws"</span>
  version = <span class="hljs-string">"~&gt; 20.31"</span>

 <span class="hljs-comment">#cluster info</span>
  cluster_name    = <span class="hljs-string">"<span class="hljs-variable">${local.name}</span>-vpc-eks"</span>
  cluster_version = <span class="hljs-string">"1.31"</span>
  cluster_endpoint_public_access = <span class="hljs-literal">true</span>

  cluster_addons = {
      vpc-cni ={
        most-recent=<span class="hljs-literal">true</span>
      }
       cube-proxy ={
        most-recent=<span class="hljs-literal">true</span>
      }
       core-dns ={
        most-recent=<span class="hljs-literal">true</span>
      }
    } 

  vpc_id                   = module.vpc.vpc_id
  subnet_ids               = module.vpc.private_subnets

  <span class="hljs-comment">#specific for control plane network </span>
  control_plane_subnet_ids = module.vpc.intra_subnets


  <span class="hljs-comment"># EKS Managed Node Group(s) managing worker nodes in cluster </span>
  eks_managed_node_group_defaults = {

    instance_types = [<span class="hljs-string">"t2.micro"</span>]
    attach_cluster_primary_security_group = <span class="hljs-literal">true</span> <span class="hljs-comment"># Attach the cluster's primary security group to the node group in order to allow communication between the nodes and the control plane</span>

  }

  eks_managed_node_groups = {
    <span class="hljs-comment"># Node group name</span>
    eks_cluster_ng = {
      instance_types  = [<span class="hljs-string">"t2.micro"</span>]

      min_size      = 2
      max_size      = 3
      desired_size  = 2
      capacity_type = <span class="hljs-string">"SPOT"</span> <span class="hljs-comment"># ON_DEMAND or SPOT</span>
    }
  }

  tags = {
    Name        = <span class="hljs-string">"<span class="hljs-variable">${local.name}</span>-vpc-eks"</span>
    Environment = local.env
  }
}
</code></pre>
<ol start="3">
<li>Now initialize terraform using init command</li>
</ol>
<pre><code class="lang-bash">$ terraform init
</code></pre>
<p>→ output for terraform init</p>
<pre><code class="lang-bash">vikrant@LAPTOP-DK2OJLBK MINGW64 ~/OneDrive/Desktop/AWSprojs/demo/terraform_eks
$ terraform init
Initializing the backend...
Initializing modules...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Reusing previous version of hashicorp/tls from the dependency lock file
- Reusing previous version of hashicorp/time from the dependency lock file
- Reusing previous version of hashicorp/cloudinit from the dependency lock file
- Reusing previous version of hashicorp/null from the dependency lock file
- Using previously-installed hashicorp/cloudinit v2.3.6
- Using previously-installed hashicorp/null v3.2.3
- Using previously-installed hashicorp/aws v5.93.0
- Using previously-installed hashicorp/tls v4.0.6
- Using previously-installed hashicorp/time v0.13.0

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running <span class="hljs-string">"terraform plan"</span> to see
any changes that are required <span class="hljs-keyword">for</span> your infrastructure. All Terraform commands
should now work.

If you ever <span class="hljs-built_in">set</span> or change modules or backend configuration <span class="hljs-keyword">for</span> Terraform,
rerun this <span class="hljs-built_in">command</span> to reinitialize your working directory. If you forget, other
commands will detect it and remind you to <span class="hljs-keyword">do</span> so <span class="hljs-keyword">if</span> necessary.
</code></pre>
<ol start="4">
<li><p>Now apply terraform plan command</p>
<pre><code class="lang-bash"> $ terraform plan
</code></pre>
</li>
</ol>
<p>→ output for terraform plan</p>
<pre><code class="lang-bash">Plan: 66 to add, 0 to change, 0 to destroy.

  + resource <span class="hljs-string">"null_resource"</span> <span class="hljs-string">"validate_cluster_service_cidr"</span> {
      + id = (known after apply)
    }

Plan: 66 to add, 0 to change, 0 to destroy.
</code></pre>
<h3 id="heading-congratulations-we-have-successfully-created-a-kubernetes-cluster-on-aws-using-aws-eks-and-terraform">🎉Congratulations we have successfully created a Kubernetes cluster on AWS using AWS EKS and terraform .</h3>
]]></content:encoded></item></channel></rss>