Deploy JMeter on AWS using Terraform
Tags: aws, terraform, performance, jmeter
Published: 2022-01-25 04:43:37

<!-- wp:paragraph -->
<p>Maintaining JMeter infrastructure for performance testing, CI/CD integration with the enterprise pipeline, and managing are cumbersome tasks. By leveraging the Infrastructure as Code solution, Terraform is one of the excellent ways to build, manage, and deploy JMeter infrastructure quickly and efficiently. In this blog, we are going to dive deeper into spinning up an AWS infrastructure with JMeter using Terraform.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>What is Infrastructure as Code?</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Infrastructure as Code (IaC) helps to build, change, and version infrastructure safely and efficiently. </p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>What is Terraform?</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Terraform is an IaC tool from HashiCorp. It comes with three flavors: CLI, Cloud, and Enterprise. Terraform's mantra is: Write, Plan, and Apply.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Terraform is an open-source infrastructure as code software tool that provides a consistent CLI workflow to manage hundreds of cloud services. Terraform codifies cloud APIs into declarative configuration&nbsp;files.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>This blog post will not enlighten you about Terraform. But it focuses on how to deploy the vanilla JMeter and JMeter plugins on AWS.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Prerequisites</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The following are the prerequisites required to deploy JMeter on AWS using Terraform.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>AWS Console access to create relevant IAM roles, access keys, and secrets</li><li>Terraform CLI</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>AWS Setup</h2>
<!-- /wp:heading -->

<!-- wp:heading {"level":3} -->
<h3>Key Pair</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>To access EC2 instances, we need to create a key pair in AWS. To create a new key pair, follow the below steps.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Log into AWS console</li><li>Navigate to EC2 -&gt; Key Pairs</li><li>Create a new key pair w/ RSA and Private Key format (PEM)</li><li>Save the private key to a file in a secure location</li></ul>
<!-- /wp:list -->

<!-- wp:image {"align":"center","id":9030,"sizeSlug":"full","linkDestination":"media"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><a href="https://qainsights.com/wp-content/uploads/2022/01/image-14.png"><img src="https://qainsights.com/wp-content/uploads/2022/01/image-14.png" alt="Creating a new key pair on AWS" class="wp-image-9030"/></a><figcaption>Creating a new key pair on AWS</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:heading {"level":3} -->
<h3>IAM User</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>To manage the AWS resources on Terraform, it is recommended to create a new IAM user with Access key credential type. To create a new IAM user, go to:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>IAM Dashboard on AWS</li><li>Click <strong>Users -&gt; Add users</strong></li><li>Enter valid user name and select <strong><code>Access key - Programmatic access</code></strong>. </li><li>Click <strong>Next: Permissions</strong></li><li>Select <strong>Attach existing policies directly</strong></li><li>Check <a href="https://console.aws.amazon.com/iam/home#/policies/arn%3Aaws%3Aiam%3A%3Aaws%3Apolicy%2FAdministratorAccess"><code>AdministratorAccess</code></a> or <code>AmazonEC2FullAccess</code></li><li>Click <strong>Next: Tags</strong>. Enter the appropriate tags.</li><li>Click <strong>Next: Review</strong></li><li>Click <strong>Create user</strong></li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>Store the Access Key ID and secret access key in a secured location. We need this info to configure it into AWS CLI.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>AWS CLI</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Download the AWS CLI from https://aws.amazon.com/cli/ </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Based on your operating system, launch the AWS CLI program and validate the version.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>aws --version</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>To configure AWS CLI, enter <code>aws configure</code> and press the enter key in the terminal. Enter the access key, secret, and other required details and configure it properly.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Terraform</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>To download Terraform, head to https://www.terraform.io/downloads and follow the instructions to download it for your operating system. In this demo, I am going to use Ubuntu 20.04 in WSL.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To validate the Terraform installation, enter <code>terraform --version</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To install, auto complete <code>terraform -install-autocomplete</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To spin the EC2 instances for JMeter, make a new directory <code>mkdir JMeter-AWS-Terraform</code>. We are going to use this directory to write some basic HCL. Terraform uses a declarative language called HashiCorp Configuration Language, which tells Terraform how to manage the resources.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>JMeter on AWS using Terraform</h2>
<!-- /wp:heading -->

<!-- wp:heading {"level":3} -->
<h3>Terraform Write</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Inside <code> JMeter-AWS-Terraform </code>, create a new file <code>main.tf</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Copy and paste the below <a href="https://registry.terraform.io/modules/QAInsights/jmeter/aws/latest" target="_blank" rel="noreferrer noopener">Terraform module</a> into <code>main.tf</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>IMPORTANT: <em>We are going to spin <code>t2.small</code> instance type in this demo which is NOT under FREE TIER. </em></strong></p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>module "jmeter" {
  source  = "QAInsights/jmeter/aws"
  version = "1.1.2"

  aws_ami           = "ami-001089eb624938d9f"
  aws_instance_type = "t2.small"
  aws_key_name      = "terraform"
  jmeter_version    = "5.4.3"
  jmeter_plugins    = &#91;"jpgc-casutg"]
}</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>The above configuration leverages the Terraform module which I have published in the Terraform registry. It expects four inputs: ami, instance type, key name, and JMeter plugins. </p>
<!-- /wp:paragraph -->

<!-- wp:buttons {"contentJustification":"center"} -->
<div class="wp-block-buttons is-content-justification-center"><!-- wp:button {"backgroundColor":"global-color-8"} -->
<div class="wp-block-button"><a class="wp-block-button__link has-global-color-8-background-color has-background" href="https://registry.terraform.io/modules/QAInsights/jmeter/aws/latest" target="_blank" rel="noreferrer noopener">JMeter Terraform Module</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->

<!-- wp:paragraph -->
<p>By default, it installs JMeter 5.4.3 and <a href="https://registry.terraform.io/modules/QAInsights/jmeter/aws/latest?tab=inputs" target="_blank" rel="noreferrer noopener">other variables</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To get started, enter <code>terraform init</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This will download the Terraform plugins, modules, and other dependencies.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Terraform Plan</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The next step is to plan the resources. The output of the below command will help us to see the resources' that will get created or changed.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Enter <code>terraform plan</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Here is the partial output of plan command.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.jmeter.module.jmeter_server.aws_instance.this will be created
  + resource "aws_instance" "this" {
      + ami                                  = "ami-001089eb624938d9f"  
      + arn                                  = (known after apply)      
      + associate_public_ip_address          = (known after apply)      
      + availability_zone                    = (known after apply)      
      + cpu_core_count                       = (known after apply)      
      + cpu_threads_per_core                 = (known after apply)      
      + disable_api_termination              = (known after apply)      
      + ebs_optimized                        = (known after apply)      
      + get_password_data                    = false


...
...
...

Plan: 1 to add, 0 to change, 0 to destroy.</code></pre>
<!-- /wp:code -->

<!-- wp:heading {"level":3} -->
<h3>Terraform Apply</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The last step in provisioning the infrastructure on AWS is to send <code>terraform apply</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>It will prompt you to review and enter <code>yes</code> to start provisioning. For automation purpose, you can use <code>terraform apply --auto-approve</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Terraform will make changes to the AWS infrastructure based on the current state. As we are spinning up the new instances, after less than a minute, a new EC2 instance will be up and running. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Launch the EC2 Instances page, navigate to the Ohio region where you can see an EC2 instance is up and running.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":9031,"sizeSlug":"full","linkDestination":"media"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><a href="https://qainsights.com/wp-content/uploads/2022/01/image-15.png"><img src="https://qainsights.com/wp-content/uploads/2022/01/image-15.png" alt="Deploy JMeter on AWS using Terraform" class="wp-image-9031"/></a><figcaption>Deploy JMeter on AWS using Terraform</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Copy the public IP address of that instance to ssh into it.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>ssh -i &lt;pem-key&gt; ec2-user@&lt;public-IP-address&gt;</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>JMeter has been installed in the home directory. To validate it, enter `jmeter -v`</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":9032,"sizeSlug":"full","linkDestination":"media"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><a href="https://qainsights.com/wp-content/uploads/2022/01/image-16.png"><img src="https://qainsights.com/wp-content/uploads/2022/01/image-16.png" alt="JMeter 5.4.3 on AWS" class="wp-image-9032"/></a><figcaption>JMeter 5.4.3 on AWS</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>The Terraform module also installs JMeter plugin <code>jpgc-casutg</code>. This can be configured in the <code>main.tf</code> file.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To validate, <code>sudo cat /var/log/cloud-init-output.log</code> to view the log.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Within a few minutes, you have an EC2 instance with Java, JMeter, and JMeter plugins for performance testing. Terraform allows us to configure all the parameters under the hood, e.g. AWS region, VPC, instance types, and more. This Terraform module uses a lot of default values for AWS. If you are looking for anything specific to configure, please let me know in the GitHub repo.</p>
<!-- /wp:paragraph -->

<!-- wp:buttons {"contentJustification":"center"} -->
<div class="wp-block-buttons is-content-justification-center"><!-- wp:button {"backgroundColor":"global-color-8"} -->
<div class="wp-block-button"><a class="wp-block-button__link has-global-color-8-background-color has-background" href="https://github.com/QAInsights/terraform-aws-jmeter" target="_blank" rel="noreferrer noopener">JMeter Terraform Module Repo</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->

<!-- wp:paragraph -->
<p>In this example, we have spun up a <code>t2.small</code> type. If you keep running, your AWS bill is going to hit the roof. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To destroy the resources, enter <code>terraform destroy --auto-approve</code>. CAUTION: This command is non-reversible.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Within a minute, EC2 instance will be deleted.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Integrating performance tests in the enterprise pipeline is crucial for shift-left and adopting DevOps practice. Managing the infrastructure for performance tests is time-consuming and error-prone. By leveraging IaC tools like Terraform, it is easy and quick to spin up the resources and destroy them once the need is done. In the next blog post, we are going to see how to deploy JMeter distributed load test infrastructure on AWS using Terraform.</p>
<!-- /wp:paragraph -->