<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Julius Etukakpan </title>
    <description>The latest articles on DEV Community by Julius Etukakpan  (@julius_etukakpan).</description>
    <link>https://dev.to/julius_etukakpan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F937325%2Fa3c52a7f-4460-4697-8c97-c9f9d2e1d753.jpeg</url>
      <title>DEV Community: Julius Etukakpan </title>
      <link>https://dev.to/julius_etukakpan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/julius_etukakpan"/>
    <language>en</language>
    <item>
      <title>Definitive Guide to Terraform: Building Secure, Highly Available, and Resilient Cloud Architectures</title>
      <dc:creator>Julius Etukakpan </dc:creator>
      <pubDate>Fri, 25 Aug 2023 09:29:52 +0000</pubDate>
      <link>https://dev.to/julius_etukakpan/definitive-guide-to-terraform-building-secure-highly-available-and-resilient-cloud-architectures-2cea</link>
      <guid>https://dev.to/julius_etukakpan/definitive-guide-to-terraform-building-secure-highly-available-and-resilient-cloud-architectures-2cea</guid>
      <description>&lt;p&gt;Welcome back to yet another learning experience with me.&lt;br&gt;
In this tutorial  you are going to learn how to use terraform to deploy a high availability and resilient cloud environment on AWS  equipped with an Auto Scaling Group (ASG) spanning two Availability Zones in private subnets of a customized VPC. The placement of an Application Load Balancer (ALB) on public subnets, along with the proper gateway and route table configurations, will be used to front the ASG.&lt;/p&gt;

&lt;p&gt;By the end of the tutorial, you'll have a firm grasp on how to use Terraform to set up a dependable and scalable cloud architecture that can manage heavy traffic loads and sustain uptime even in the case of component failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with and understanding of the fundamental Terraform basic concepts and commands&lt;/li&gt;
&lt;li&gt;  Understanding of the Linux command line&lt;/li&gt;
&lt;li&gt;  IAM user with administrative rights on an AWS account&lt;/li&gt;
&lt;li&gt;  Pair of Amazon EC2 keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Case Study&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An e-commerce business, JULS EXPRESS, must manage an increase in traffic over the Holiday's season. This organization wants to make sure that even during times of high traffic, its website is accessible and responsive to users.&lt;/p&gt;

&lt;p&gt;Your employer has given you the task of setting up an AWS cloud infrastructure that will provide high availability and resilient You decide to setup an EC2 Auto Scaling Group (ASG) in private subnets fronted by an Application Load Balancer (ALB) in public subnets using Terraform to automate infrastructure. This ASG will automatically scale up or down based on traffic, ensuring that the website is always responsive to users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Objectives&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a custom Virtual Private Network (VPC) Using two public subnets and two private subnets in two different Availability Zones,&lt;/li&gt;
&lt;li&gt;    Use an Internet Gateway and a NAT Gateway on the public subnet to enable outgoing internet traffic.&lt;/li&gt;
&lt;li&gt;    Create a private route table and a public route table.&lt;/li&gt;
&lt;li&gt;    In the public subnets, start the ALB.&lt;/li&gt;
&lt;li&gt;    Open the private subnets and launch the Auto Scaling group.&lt;/li&gt;
&lt;li&gt;    Release the ALB's public DNS, and then use its URL to confirm that the web servers can be reached.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without any further delay, let us begin the tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrzdxkgw9g5givi5o2au.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrzdxkgw9g5givi5o2au.gif" alt="let's start"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Establishing and setting up a unique AWS VPC&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our first goal is to create a unique VPC in our AWS environment where we can deploy all of our resources. To do this, a logically isolated CIDR block must be defined, and the suitable subnets and accompanying availability zones (AZ) to deploy them in must be carefully chosen.&lt;/p&gt;

&lt;p&gt;Let's scrutinize the code in the paragraphs that follow Terraform file to establish and set up the unique VPC —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create an AWS VPC
resource "aws_vpc" "terraform-vpc" {
  cidr_block       = var.vpc-cidr
  instance_tenancy = "default"

  tags = {
    Name = var.vpc_name
  }
}

# Create first public subnet in the VPC
resource "aws_subnet" "pub-sub1" {
  vpc_id                  = aws_vpc.terraform-vpc.id
  cidr_block              = var.pub_sub1_cidr
  availability_zone       = var.availability_zone-1
  map_public_ip_on_launch = true

  tags = {
    Name = var.pub-sub1-name
  }
}

# Create second public subnet in the VPC
resource "aws_subnet" "pub-sub2" {
  vpc_id                  = aws_vpc.terraform-vpc.id
  cidr_block              = var.pub_sub2_cidr
  availability_zone       = var.availability_zone-2
  map_public_ip_on_launch = true

  tags = {
    Name = var.pub-sub2-name
  }
}

# Create first private subnet in the VPC
resource "aws_subnet" "priv-sub1" {
  vpc_id                  = aws_vpc.terraform-vpc.id
  cidr_block              = var.priv_sub1_cidr
  availability_zone       = var.availability_zone-1
  map_public_ip_on_launch = true

  tags = {
    Name = var.priv-sub1-name
  }
}

# Create second private subnet in the VPC
resource "aws_subnet" "priv-sub2" {
  vpc_id                  = aws_vpc.terraform-vpc.id
  cidr_block              = var.priv_sub2_cidr
  availability_zone       = var.availability_zone-2
  map_public_ip_on_launch = true

  tags = {
    Name = var.priv-sub2-name
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here, a particular CIDR block and instance tenancy are used to build an AWS VPC. Then, two public and two private subnets are created. Each subnet is designed to be deployed in certain availability zones, has a specific CIDR block, and is connected to the VPC that was previously constructed.&lt;/p&gt;

&lt;p&gt;Instances started on public subnets will immediately receive a public IP address since those subnets have the map_public_ip_on_launch attribute set to true. That property is set to false for the private subnets, so instances launched there won't be reachable from the internet unless they go via a NAT gateway that we'll set up in the following step. A tag is used to assign a name to each subnet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Setup a NAT and Internet gateway in the public subnet.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is essential to make sure that resources are securely and effectively linked to the internet before putting them in the VPC. Making an Internet Gateway and NAT Gateway in a public subnet is one technique to do this.&lt;/p&gt;

&lt;p&gt;A VPC component called an Internet Gateway enables connectivity between instances in a VPC and the internet. In the meantime, a NAT Gateway is used to allow connections from instances in private subnets to the internet or other AWS services while additionally securing outbound traffic.&lt;/p&gt;

&lt;p&gt;Examine the code of the Terraform file that creates and configures an Internet Gateway and NAT Gateway in the section below. —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create an internet gateway and associate it with the VPC
resource "aws_internet_gateway" "terraform-igw" {
  vpc_id = aws_vpc.terraform-vpc.id

  tags = {
    Name = var.igw-name
  }
}

# Create an Elastic IP address
resource "aws_eip" "ngw-eip" {
  vpc = true
}

# Create a NAT gateway and associate it with an Elastic IP and a public subnet
resource "aws_nat_gateway" "terraform-ngw" {
  allocation_id = aws_eip.ngw-eip.id     # Associate the NAT gateway with the Elastic IP
  subnet_id     = aws_subnet.pub-sub1.id # Associate the NAT gateway with a public subnet

  tags = {
    Name = var.nat-gw-name
  }

  depends_on = [aws_internet_gateway.terraform-igw] # Make sure the internet gateway is created before creating the NAT gateway
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, we setup an Internet Gateway and attach it to the unique VPC. Additionally, we establish a NAT Gateway, an Elastic IP address, and connect them to a public subnet. Additionally, we make sure to construct the Internet Gateway before the NAT Gateway.&lt;/p&gt;

&lt;p&gt;Great! Now that our NAT gateway and Internet gateway have been established, we can go on to Step 3 and configure our public and private route tables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Set up a a public route table and a private route table&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have now successfully setup the gateways and the customized VPC. The issue which we now have, though, is how to control communication between the services and other VPC-deployed components. At this point, it is necessary to configure the network traffic flow within the VPC. Setting up routing tables to guide network traffic between the subnets is one efficient approach to accomplish this.&lt;/p&gt;

&lt;p&gt;Let's look at the code below to see how to establish and set up each of our individual route tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Creates a public route table with a default route to the internet gateway
resource "aws_route_table" "pub-rt" {
  vpc_id = aws_vpc.terraform-vpc.id

  # Create a default route for the internet gateway with destination 0.0.0.0/0
  route {
    cidr_block = var.pub_rt_cidr
    gateway_id = aws_internet_gateway.terraform-igw.id
  }

  tags = {
    Name = var.pub-rt-name
  }
}

# Creates a private route table with a default route to the NAT gateway
resource "aws_route_table" "priv-rt" {
  vpc_id = aws_vpc.terraform-vpc.id

  route {
    cidr_block = var.priv_rt_cidr
    gateway_id = aws_nat_gateway.terraform-ngw.id
  }

  tags = {
    Name = var.priv-rt-name
  }
}

# Associates the public route table with the public subnet 1
resource "aws_route_table_association" "pub-sub1-rt-ass" {
  subnet_id      = aws_subnet.pub-sub1.id
  route_table_id = aws_route_table.pub-rt.id
}

# Associates the public route table with the public subnet 2
resource "aws_route_table_association" "pub-sub2-rt-ass" {
  subnet_id      = aws_subnet.pub-sub2.id
  route_table_id = aws_route_table.pub-rt.id
}

# Associates the private route table with the private subnet 1
resource "aws_route_table_association" "priv-sub1-rt-ass" {
  subnet_id      = aws_subnet.priv-sub1.id
  route_table_id = aws_route_table.priv-rt.id

  # Wait for the private route table to be created before creating this association
  depends_on = [aws_route_table.priv-rt]
}

# Associates the private route table with the private subnet 2
resource "aws_route_table_association" "priv-sub2-rt-ass" {
  subnet_id      = aws_subnet.priv-sub2.id
  route_table_id = aws_route_table.priv-rt.id

  # Wait for the private route table to be created before creating this association
  depends_on = [aws_route_table.priv-rt]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A public route table and a private route table are being created here. Both the private and public route tables include default routes to the NAT Gateway and the Internet Gateway, respectively.&lt;/p&gt;

&lt;p&gt;The two public subnets are connected to the public route table, while the two private subnets are connected to the private route table. The private route table must exist prior to the creation of the private resource associations. Using tags, names have also been given to the route tables.&lt;/p&gt;

&lt;p&gt;Now let's move on to Step 4 where we will Launch a fresh ALB in the open subsets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.Launch the ALB in the public subnet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's look into how to launch an ALB in the public subnets of the unique VPC. There are various phases involved in setting up an ALB, such as creating a Security Group, configuring Target Groups, listeners, and routing rules.&lt;/p&gt;

&lt;p&gt;Review the Terraform code below, which sets up a Security Group connected to our ALB-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create security group for ALB
resource "aws_security_group" "alb-sg" {
  # Set name and description of the security group
  name        = var.alb_sg_name
  description = var.alb_sg_description

  # Set the VPC ID where the security group will be created
  vpc_id     = aws_vpc.terraform-vpc.id
  depends_on = [aws_vpc.terraform-vpc]

  # Inbound Rule
  # HTTP access from anywhere
  ingress {
    description = "Allow HTTP Traffic"
    from_port   = var.http_port
    to_port     = var.http_port
    protocol    = "tcp"
    cidr_blocks = var.alb_sg_ingress_cidr_blocks
  }

  # SSH access from anywhere
  ingress {
    description = "Allow SSH Traffic"
    from_port   = var.ssh_port
    to_port     = var.ssh_port
    protocol    = "tcp"
    cidr_blocks = var.alb_sg_ingress_cidr_blocks
  }

  # Inbound Rule
  # Allow all egress traffic
  egress {
    from_port   = "0"
    to_port     = "0"
    protocol    = "-1"
    cidr_blocks = var.alb_sg_egress_cidr_blocks
  }

  # Set tags for the security group
  tags = {
    Name = "ALB SG"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We set up a Security Group in this Terraform code that will work with the ALB. The custom VPC is connected to the Security Group, which is defined with a name and description.&lt;/p&gt;

&lt;p&gt;It has egress rules that permit all traffic and entrance rules that permit HTTP and SSH traffic from a certain CIDR block. In order to make the Security Group easier to identify, we also give it a name.&lt;/p&gt;

&lt;p&gt;Now that the ALB has been created and configured, we can review the code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create a new load balancer
resource "aws_lb" "pub-sub-alb" {
  name            = var.load_balancer_name
  subnets         = [aws_subnet.pub-sub1.id, aws_subnet.pub-sub2.id]
  security_groups = [aws_security_group.alb-sg.id]

  tags = {
    Name = "Pub-Sub-ALB"
  }
}

# Create a target group for the load balancer
resource "aws_lb_target_group" "alb-tg" {
  name     = var.target_group_name
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.terraform-vpc.id

  # Set the health check configuration for the target group
  health_check {
    interval = 60
    path     = "/"
    port     = 80
    timeout  = 45
    protocol = "HTTP"
    matcher  = "200,202"
  }
}


# Create ALB listener
resource "aws_lb_listener" "alb-listener" {
  load_balancer_arn = aws_lb.pub-sub-alb.arn
  port              = "80"
  protocol          = "HTTP"

  # Set the default action for the listener
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.alb-tg.arn
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here, we construct an ALB and the resources it needs. The ALB is first created, and then the name, subnets, and security groups are specified.&lt;/p&gt;

&lt;p&gt;We then create a Target Group with the name, port, protocol, and settings for the health check for the ALB to direct traffic to.&lt;/p&gt;

&lt;p&gt;The last step is to build a listener for the ALB, defining the port and protocol to use, and setting the default action to send traffic to the previously formed Target Group. As a result, traffic may be routed to the correct resources based on the configuration of the Target Group and the listener rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Open the private subnets and start the Auto Scaling Group.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While private subnets are frequently chosen in situations involving sensitive data or regulatory compliance, Auto Scaling Groups (ASG) are frequently implemented in public subnets.&lt;/p&gt;

&lt;p&gt;Let's examine the code that launches an EC2 ASG across two Availability Zones (AZ) on private subnets using the methods listed below —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Creating Security Group for ASG Launch Template
resource "aws_security_group" "lt-sg" {
  name   = var.lt_sg_name
  vpc_id = aws_vpc.terraform-vpc.id

  # Inbound Rules
  # HTTP access from anywhere
  ingress {
    from_port       = var.http_port
    to_port         = var.http_port
    protocol        = "tcp"
    security_groups = [aws_security_group.alb-sg.id]
  }

  # SSH access from anywhere
  ingress {
    from_port       = var.ssh_port
    to_port         = var.ssh_port
    protocol        = "tcp"
    security_groups = [aws_security_group.alb-sg.id]
  }

  # Outbound Rules
  # Internet access to anywhere
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = var.lt_sg_egress_cidr_blocks
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, a Security Group for the ASG Launch Template must be built and linked to the previously established custom VPC.&lt;/p&gt;

&lt;p&gt;The Security Group only permits incoming HTTP and SSH communication from the Security Group for the ALB, which is specified in a separate resource. As only the ALB may get access to our ASG, this increases security. We also permit outbound traffic to any location with a CIDR block given in a defined variable since Security Groups are stateful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shell Script&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will first create a bash script that will be put into the ASG's Launch Template in order to get ready to create our ASG. This script will act as the user data for the EC2 instance, automating the setup and start-up of the Apache web service as well as the production of a unique web page.&lt;/p&gt;

&lt;p&gt;Go over the bash script that is below please feel free to edit the html part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

#Update all yum package repositories
yum update -y

#Install Apache Web Server
yum install -y httpd.x86_64

#Start and Enable Apache Web Server
systemctl start httpd.service
systemctl enable httpd.service

#Install epel for easy access to install packages for commonly used software
amazon-linux-extras install epel -y

#Install stress to enable us to test EC2 Instance under stress work loads
yum install stress -y

#Adds our custom webpage html code to "index.html" file.
echo "&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Welcome to Juls Express!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;html&amp;gt;" &amp;gt; /var/www/html/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Code Interpretation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Apache Web Server package is installed using yum in this script when all the yum package repositories have been updated. To make sure the Apache service begins when the computer boots, we must start and activate it.&lt;/p&gt;

&lt;p&gt;The Extra Packages for Enterprise Linux (EPEL) repository, which enables simple installation of widely used software packages, is also installed by the script.&lt;/p&gt;

&lt;p&gt;The stress package is also installed by the script, which may be used to test the instance under demanding workloads. Last but not least, the script replaces the standard index.html file in the Apache document root directory /var/www/html/ with a customized webpage with a Welcome to Juls express! message.&lt;/p&gt;

&lt;p&gt;After you have created all of these files, you may execute the following commands to build your deploy a high availability and resilient cloud environment:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command helps Terraform get started and downloads the required provider plugins, in this instance the AWS provider.&lt;/p&gt;

&lt;p&gt;To create a list of all the adjustments Terraform will make, let's run the following command. —&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It should be possible to see a list of the adjustments Terraform is expected to make to the infrastructure resources. What will be added is indicated by the "+" symbol, and what will be deleted is indicated by the "-" sign.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe5nptae676f53zd4c0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe5nptae676f53zd4c0z.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's proceed with setting this infrastructure in place! To implement the modifications and allocate the resources, run the following command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform apply -auto-approve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command allows you to apply everything that has been written to your AWS account and it also stop the prompt that will require you too type the "yes" command to proceed with deployment&lt;/p&gt;

&lt;p&gt;Excellent!&lt;/p&gt;

&lt;p&gt;The procedure should now come to an end with a message that says "Apply complete" and lists the total number of resources that were added, updated, and removed along with a number of resource outputs.&lt;/p&gt;

&lt;p&gt;The ALB's DNS URL must be copied and saved in order to visit the website from a browser.&lt;/p&gt;

&lt;p&gt;Let's check the Management Console to see whether our resources have been established there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Confirm that an EC2 instance was created from an ASG and that the target group is healthy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sxm287xul1edyunifbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sxm287xul1edyunifbd.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Also, select Target groups in the left pane by scrolling down. Verify that the instances' Health state is healthy by selecting the newly established Target group, scrolling down, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4063gzr3emp5lonaoj4s.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4063gzr3emp5lonaoj4s.jpeg" alt="target group"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! Our ASG created expected EC2 instances, and we have successfully verified that all of our Target groups' health statuses are showing as healthy. Let's check if our ALB can connect to our ASG's web servers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. Using the Web server's URL in a browser, confirm that it can be reached.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Copy the DNS URL for the ALB and paste it into your preferred browser.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: When contacting the ALB, be sure to utilize the "http://" rather than the "https://" protocol.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9dd4sl8rl54a9fkx42t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9dd4sl8rl54a9fkx42t.png" alt="ALB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations!&lt;br&gt;
You now know how to use Terraform to create a dependable, scalable cloud architecture that can manage heavy traffic loads and continue to function even when individual components fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Destroy infrastructure and clean up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To remove/delete/tear down all previously provisioned resources from Terraform, use the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform destroy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wait for it to finish. You ought to get a prompt at the conclusion saying "Destroy complete" together with the quantity of resources that were destroyed.&lt;/p&gt;

&lt;p&gt;If you've read this far, I appreciate it. I hope you found it helpful . see you in the next one&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>cloudcomputing</category>
      <category>architecture</category>
      <category>terraform</category>
    </item>
    <item>
      <title>The Easiest Way To Create An EKS Cluster With Terraform</title>
      <dc:creator>Julius Etukakpan </dc:creator>
      <pubDate>Sun, 20 Aug 2023 10:16:04 +0000</pubDate>
      <link>https://dev.to/julius_etukakpan/the-easiest-way-to-create-an-eks-cluster-with-terraform-1d6c</link>
      <guid>https://dev.to/julius_etukakpan/the-easiest-way-to-create-an-eks-cluster-with-terraform-1d6c</guid>
      <description>&lt;p&gt;Welcome back to yet another learning experience with me.&lt;br&gt;
In this tutorial, you are going to learn how to use Terraform to setup an EKS cluster, a VPC, and subnets.&lt;br&gt;
At the end  of the tutorial You will have achieved the following objectives :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to set up Node and EKS cluster roles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to use Terraform to create an EKS cluster with the appropriate roles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to configure your cluster's VPC and subnets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to Set up a Node Group.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following are the prerequisites for following the guide below in the creation of your EKS cluster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An active AWS account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An Ubuntu Machine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terraform installed on the machine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWS CLI&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without any further delay, let us begin the tutorial.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjiy3nkz80a6ieo7qcex.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjiy3nkz80a6ieo7qcex.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. CREATING THE EKS PROVIDER BLOCK&lt;/strong&gt;&lt;br&gt;
This part of our tutorial involves the creation of the provider block.&lt;br&gt;
The provider block helps terraform to interact with other cloud providers and APIs &lt;br&gt;
To get started you will create first have to crate a new file and name it “provider.tf”&lt;br&gt;
In this file you will define AWS as our provider and our specific region is us-east-1&lt;br&gt;
This is subject to change so please feel free to change the region to your preferred one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "us-east-1"
}

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&amp;gt; 3.0"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Creating THE VPC&lt;/strong&gt;&lt;br&gt;
This  part will involve the creation of vpc for our EKS cluster&lt;br&gt;
The name tag on this vpc will be called “main” and it will have a Cidr_block of “10.0.0.0 /16”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "main"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.CREATING AN INTERNET GATEWAY&lt;/strong&gt;&lt;br&gt;
   Up next we will create the internet gateway this enables resources in your public subnet for example EC2 instance  to connect to the internet if they have a public IPV6 or IPV4 address&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "igw"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The internet gateway will use the VPC ID to attach itself to the VPC. You also need a name tag for this resource, and I have chosen ‘igw’ for this project’s internet gateway. Feel free to rename it if you like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.CREATION OF SUBNETS&lt;/strong&gt;&lt;br&gt;
 Next we will be creating two subnets in the VPC, public and private, and two availability zones will be attached to them&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_subnet" "private-us-east-1a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.0.0/19"
  availability_zone = "us-east-1a"

  tags = {
    "Name"                            = "private-us-east-1a"
    "kubernetes.io/role/internal-elb" = "1"
    "kubernetes.io/cluster/demo"      = "owned"
  }
}

resource "aws_subnet" "private-us-east-1b" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.32.0/19"
  availability_zone = "us-east-1b"

  tags = {
    "Name"                            = "private-us-east-1b"
    "kubernetes.io/role/internal-elb" = "1"
    "kubernetes.io/cluster/demo"      = "owned"
  }
}

resource "aws_subnet" "public-us-east-1a" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.64.0/19"
  availability_zone       = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    "Name"                       = "public-us-east-1a"
    "kubernetes.io/role/elb"     = "1"
    "kubernetes.io/cluster/demo" = "owned"
  }
}

resource "aws_subnet" "public-us-east-1b" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.96.0/19"
  availability_zone       = "us-east-1b"
  map_public_ip_on_launch = true

  tags = {
    "Name"                       = "public-us-east-1b"
    "kubernetes.io/role/elb"     = "1"
    "kubernetes.io/cluster/demo" = "owned"
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5.NATGATEWAY AND ELASTIC IP&lt;/strong&gt;&lt;br&gt;
 Next step is to create a NAT gateway and an elastic IP.&lt;br&gt;
The elastic IP will be attached to the NAT gateway and also connected to a public subnet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_eip" "nat" {
  vpc = true

  tags = {
    Name = "nat"
  }
}

resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public-us-east-1a.id

  tags = {
    Name = "nat"
  }

  depends_on = [aws_internet_gateway.igw]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;provisioning of an Internet Gateway is what the NAT gateway requires first, and our name tag for the NAT gateway will be “nat” (feel free to change it if you like).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.ROUTE TABLES&lt;/strong&gt;&lt;br&gt;
A route table is a set of rules that determine the direction of network traffic from your subnet or gateway.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route = [
    {
      cidr_block                 = "0.0.0.0/0"
      nat_gateway_id             = aws_nat_gateway.nat.id
      carrier_gateway_id         = ""
      destination_prefix_list_id = ""
      egress_only_gateway_id     = ""
      gateway_id                 = ""
      instance_id                = ""
      ipv6_cidr_block            = ""
      local_gateway_id           = ""
      network_interface_id       = ""
      transit_gateway_id         = ""
      vpc_endpoint_id            = ""
      vpc_peering_connection_id  = ""
    },
  ]

  tags = {
    Name = "private"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route = [
    {
      cidr_block                 = "0.0.0.0/0"
      gateway_id                 = aws_internet_gateway.igw.id
      nat_gateway_id             = ""
      carrier_gateway_id         = ""
      destination_prefix_list_id = ""
      egress_only_gateway_id     = ""
      instance_id                = ""
      ipv6_cidr_block            = ""
      local_gateway_id           = ""
      network_interface_id       = ""
      transit_gateway_id         = ""
      vpc_endpoint_id            = ""
      vpc_peering_connection_id  = ""
    },
  ]

  tags = {
    Name = "public"
  }
}

resource "aws_route_table_association" "private-us-east-1a" {
  subnet_id      = aws_subnet.private-us-east-1a.id
  route_table_id = aws_route_table.private.id
}

resource "aws_route_table_association" "private-us-east-1b" {
  subnet_id      = aws_subnet.private-us-east-1b.id
  route_table_id = aws_route_table.private.id
}

resource "aws_route_table_association" "public-us-east-1a" {
  subnet_id      = aws_subnet.public-us-east-1a.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "public-us-east-1b" {
  subnet_id      = aws_subnet.public-us-east-1b.id
  route_table_id = aws_route_table.public.id
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will create a routing table for both the public and private subnets.&lt;br&gt;
The empty spaces are just a default, you can make changes to them if you want.&lt;br&gt;
The next step is to  attach the route table  to each availability zone. We will then connect each Route Table to the VPC created above. Feel free to change the name tag if you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7.CREATING THE EKS CLUSTER WITH ROLE&lt;/strong&gt;&lt;br&gt;
The  service-linked role called &lt;strong&gt;AWSServiceRoleForAmazonEKS&lt;/strong&gt; is used by Amazon EKS for cluster management in your account&lt;br&gt;
The attached policies allow the role to manage the following resources: network interfaces, security groups, logs, and VPCs.&lt;br&gt;
In this section, we will create an EKS cluster with a role.&lt;br&gt;
However, we will first create an IAM role policy and connect it to the public and private subnets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "demo" {
  name = "eks-cluster-demo"

  assume_role_policy = &amp;lt;&amp;lt;POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "demo-AmazonEKSClusterPolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.demo.name
}

resource "aws_eks_cluster" "demo" {
  name     = "demo"
  role_arn = aws_iam_role.demo.arn

  vpc_config {
    subnet_ids = [
      aws_subnet.private-us-east-1a.id,
      aws_subnet.private-us-east-1b.id,
      aws_subnet.public-us-east-1a.id,
      aws_subnet.public-us-east-1b.id
    ]
  }

  depends_on = [aws_iam_role_policy_attachment.demo-AmazonEKSClusterPolicy]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;8.EKS NODE GROUP &amp;amp; OPENID&lt;/strong&gt;&lt;br&gt;
We will now create a node group for our EKS cluster.&lt;br&gt;
This node group will need to be attached to three roles policies which are: nodes-AmazonEKSWorkerNodePolicy, nodes-AmazonEKS_CNI_Policy, and nodes-AmazonEC2ContainerRegistryReadOnly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "nodes" {
  name = "eks-node-group-nodes"

  assume_role_policy = jsonencode({
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
    Version = "2012-10-17"
  })
}

resource "aws_iam_role_policy_attachment" "nodes-AmazonEKSWorkerNodePolicy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
  role       = aws_iam_role.nodes.name
}

resource "aws_iam_role_policy_attachment" "nodes-AmazonEKS_CNI_Policy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
  role       = aws_iam_role.nodes.name
}

resource "aws_iam_role_policy_attachment" "nodes-AmazonEC2ContainerRegistryReadOnly" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  role       = aws_iam_role.nodes.name
}

resource "aws_eks_node_group" "private-nodes" {
  cluster_name    = aws_eks_cluster.demo.name
  node_group_name = "private-nodes"
  node_role_arn   = aws_iam_role.nodes.arn

  subnet_ids = [
    aws_subnet.private-us-east-1a.id,
    aws_subnet.private-us-east-1b.id
  ]

  capacity_type  = "ON_DEMAND"
  instance_types = ["t3.small"]

  scaling_config {
    desired_size = 2
    max_size     = 5
    min_size     = 0
  }

  update_config {
    max_unavailable = 1
  }

  labels = {
    role = "general"
  }

  # taint {
  #   key    = "team"
  #   value  = "devops"
  #   effect = "NO_SCHEDULE"
  # }

  # launch_template {
  #   name    = aws_launch_template.eks-with-disks.name
  #   version = aws_launch_template.eks-with-disks.latest_version
  # }

  depends_on = [
    aws_iam_role_policy_attachment.nodes-AmazonEKSWorkerNodePolicy,
    aws_iam_role_policy_attachment.nodes-AmazonEKS_CNI_Policy,
    aws_iam_role_policy_attachment.nodes-AmazonEC2ContainerRegistryReadOnly,
  ]
}

/* resource "aws_eks_node_group" "public-nodes" {
  cluster_name    = aws_eks_cluster.demo.name
  node_group_name = "public-nodes"
  node_role_arn   = aws_iam_role.nodes.arn

  subnet_ids = [
    aws_subnet.public-us-east-1a.id,
    aws_subnet.public-us-east-1b.id
  ]

  capacity_type  = "ON_DEMAND"
  instance_types = ["t3.small"]

  scaling_config {
    desired_size = 2
    max_size     = 5
    min_size     = 0
  }

  update_config {
    max_unavailable = 1
  }

  labels = {
    role = "general"
  }

  # taint {
  #   key    = "team"
  #   value  = "devops"
  #   effect = "NO_SCHEDULE"
  # }

  # launch_template {
  #   name    = aws_launch_template.eks-with-disks.name
  #   version = aws_launch_template.eks-with-disks.latest_version
  # }

  depends_on = [
    aws_iam_role_policy_attachment.nodes-AmazonEKSWorkerNodePolicy,
    aws_iam_role_policy_attachment.nodes-AmazonEKS_CNI_Policy,
    aws_iam_role_policy_attachment.nodes-AmazonEC2ContainerRegistryReadOnly,
  ]
}
 */
# resource "aws_launch_template" "eks-with-disks" {
#   name = "eks-with-disks"

#   key_name = "local-provisioner"

#   block_device_mappings {
#     device_name = "/dev/xvdb"

#     ebs {
#       volume_size = 50
#       volume_type = "gp2"
#     }
#   }
# }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are only setting up private nodes for this project, which implies the nodes will be in the private subnet.&lt;br&gt;
If you want the nodes to be public, you may edit the code.&lt;br&gt;
We are also setting up autoscaling with two desirable states, five maximum states, and zero minimum states.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OPENID&lt;/strong&gt;&lt;br&gt;
IAM OIDC identity providers are entities in IAM that represent an external identity provider (IdP) service, such as Google or Salesforce, that implements the OpenID Connect (OIDC) standard.&lt;br&gt;
When you want to create trust between an OIDC-compatible IdP and your AWS account, you utilize an IAM OIDC identity provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "tls_certificate" "eks" {
  url = aws_eks_cluster.demo.identity[0].oidc[0].issuer
}

resource "aws_iam_openid_connect_provider" "eks" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.tls_certificate.eks.certificates[0].sha1_fingerprint]
  url             = aws_eks_cluster.demo.identity[0].oidc[0].issuer
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OPENID TEST&lt;/strong&gt;&lt;br&gt;
This test allows us to associate a policy with our OpenID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_iam_policy_document" "test_oidc_assume_role_policy" {
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    effect  = "Allow"

    condition {
      test     = "StringEquals"
      variable = "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:sub"
      values   = ["system:serviceaccount:default:aws-test"]
    }

    principals {
      identifiers = [aws_iam_openid_connect_provider.eks.arn]
      type        = "Federated"
    }
  }
}

resource "aws_iam_role" "test_oidc" {
  assume_role_policy = data.aws_iam_policy_document.test_oidc_assume_role_policy.json
  name               = "test-oidc"
}

resource "aws_iam_policy" "test-policy" {
  name = "test-policy"

  policy = jsonencode({
    Statement = [{
      Action = [
        "s3:ListAllMyBuckets",
        "s3:GetBucketLocation"
      ]
      Effect   = "Allow"
      Resource = "arn:aws:s3:::*"
    }]
    Version = "2012-10-17"
  })
}

resource "aws_iam_role_policy_attachment" "test_attach" {
  role       = aws_iam_role.test_oidc.name
  policy_arn = aws_iam_policy.test-policy.arn
}

output "test_policy_arn" {
  value = aws_iam_role.test_oidc.arn
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;9.AUTOSCALER&lt;/strong&gt;&lt;br&gt;
We will create an autoscaling role for our EKS cluster in this section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data "aws_iam_policy_document" "eks_cluster_autoscaler_assume_role_policy" {
  statement {
    actions = ["sts:AssumeRoleWithWebIdentity"]
    effect  = "Allow"

    condition {
      test     = "StringEquals"
      variable = "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:sub"
      values   = ["system:serviceaccount:kube-system:cluster-autoscaler"]
    }

    principals {
      identifiers = [aws_iam_openid_connect_provider.eks.arn]
      type        = "Federated"
    }
  }
}

resource "aws_iam_role" "eks_cluster_autoscaler" {
  assume_role_policy = data.aws_iam_policy_document.eks_cluster_autoscaler_assume_role_policy.json
  name               = "eks-cluster-autoscaler"
}

resource "aws_iam_policy" "eks_cluster_autoscaler" {
  name = "eks-cluster-autoscaler"

  policy = jsonencode({
    Statement = [{
      Action = [
                "autoscaling:DescribeAutoScalingGroups",
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeLaunchConfigurations",
                "autoscaling:DescribeTags",
                "autoscaling:SetDesiredCapacity",
                "autoscaling:TerminateInstanceInAutoScalingGroup",
                "ec2:DescribeLaunchTemplateVersions"
            ]
      Effect   = "Allow"
      Resource = "*"
    }]
    Version = "2012-10-17"
  })
}

resource "aws_iam_role_policy_attachment" "eks_cluster_autoscaler_attach" {
  role       = aws_iam_role.eks_cluster_autoscaler.name
  policy_arn = aws_iam_policy.eks_cluster_autoscaler.arn
}

output "eks_cluster_autoscaler_arn" {
  value = aws_iam_role.eks_cluster_autoscaler.arn
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you have created all of these files, you may execute the following commands to build your EKS cluster:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command aids in the initialization of Terraform and the download of the necessary provider plugins, which in this case is the AWS provider.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform apply -auto-approve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command allows you to apply everything that has been written to your AWS account. And when this works properly.&lt;/p&gt;

&lt;p&gt;Check your AWS account to see if the cluster is up and functioning. As shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71wrvvt09dmcu88logg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71wrvvt09dmcu88logg2.png" alt="cluster"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above shows the EKS cluster fully functioning, as well as the node groups we formed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpf2muo03h7q0olil2woq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpf2muo03h7q0olil2woq.png" alt="Node groups"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please keep in mind that if you altered the name of these resources while putting them up in the files, you may have a new name for them now.&lt;/p&gt;

&lt;p&gt;And there you have it, an EKS cluster in roughly 15 minutes! Use the following command to connect to your cluster:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ aws eks --region example_region update-kubeconfig --name cluster_name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the code above, edit example_region with the region where your cluster is running, and cluster_name with the name of the cluster you created.&lt;/p&gt;

&lt;p&gt;You've finally finished building an eks cluster. Congratulations!!&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>terraform</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
